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
51 #include "wine/port.h"
60 #define NONAMELESSUNION
71 #include "wine/unicode.h"
74 #include "wine/debug.h"
77 #include "wine/heap.h"
78 #include "wine/list.h"
80 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
81 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
95 WORD type_id
; /* Type identifier */
96 WORD count
; /* Number of resources of this type */
97 DWORD resloader
; /* SetResourceHandler() */
103 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
104 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
105 static void TLB_FreeVarDesc(VARDESC
*);
107 /****************************************************************************
110 * Takes p_iVal (which is in little endian) and returns it
111 * in the host machine's byte order.
113 #ifdef WORDS_BIGENDIAN
114 static WORD
FromLEWord(WORD p_iVal
)
116 return (((p_iVal
& 0x00FF) << 8) |
117 ((p_iVal
& 0xFF00) >> 8));
121 static DWORD
FromLEDWord(DWORD p_iVal
)
123 return (((p_iVal
& 0x000000FF) << 24) |
124 ((p_iVal
& 0x0000FF00) << 8) |
125 ((p_iVal
& 0x00FF0000) >> 8) |
126 ((p_iVal
& 0xFF000000) >> 24));
129 #define FromLEWord(X) (X)
130 #define FromLEDWord(X) (X)
133 #define DISPATCH_HREF_OFFSET 0x01000000
134 #define DISPATCH_HREF_MASK 0xff000000
136 /****************************************************************************
139 * Fix byte order in any structure if necessary
141 #ifdef WORDS_BIGENDIAN
142 static void FromLEWords(void *p_Val
, int p_iSize
)
146 p_iSize
/= sizeof(WORD
);
149 *Val
= FromLEWord(*Val
);
156 static void FromLEDWords(void *p_Val
, int p_iSize
)
160 p_iSize
/= sizeof(DWORD
);
163 *Val
= FromLEDWord(*Val
);
169 #define FromLEWords(X,Y) /*nothing*/
170 #define FromLEDWords(X,Y) /*nothing*/
174 * Find a typelib key which matches a requested maj.min version.
176 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
178 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
182 INT best_maj
= -1, best_min
= -1;
185 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
186 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
188 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
191 len
= sizeof(key_name
);
193 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
197 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
199 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
201 if (*wMaj
== 0xffff && *wMin
== 0xffff)
203 if (v_maj
> best_maj
) best_maj
= v_maj
;
204 if (v_min
> best_min
) best_min
= v_min
;
206 else if (*wMaj
== v_maj
)
213 break; /* exact match */
215 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
218 len
= sizeof(key_name
);
222 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
224 if (*wMaj
== 0xffff && *wMin
== 0xffff)
226 if (best_maj
>= 0 && best_min
>= 0)
234 if (*wMaj
== best_maj
&& best_min
>= 0)
242 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
243 /* buffer must be at least 60 characters long */
244 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
246 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
247 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
249 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
250 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
251 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
255 /* get the path of an interface key, in the form "Interface\\<guid>" */
256 /* buffer must be at least 50 characters long */
257 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
259 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
261 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
262 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
266 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
267 /* buffer must be at least 16 characters long */
268 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
270 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
271 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
272 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
273 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
275 sprintfW( buffer
, LcidFormatW
, lcid
);
278 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
279 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
280 case SYS_WIN64
: strcatW( buffer
, win64W
); break;
282 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
288 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
290 struct tlibredirect_data
304 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
305 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
306 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
308 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
312 WCHAR Path
[MAX_PATH
];
315 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
319 ACTCTX_SECTION_KEYED_DATA data
;
321 data
.cbSize
= sizeof(data
);
322 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
324 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
328 if ((wMaj
!= 0xffff || wMin
!= 0xffff) && (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
))
329 return TYPE_E_LIBNOTREGISTERED
;
331 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
332 len
= SearchPathW( NULL
, nameW
, NULL
, ARRAY_SIZE( Path
), Path
, NULL
);
333 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
335 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
336 *path
= SysAllocString( Path
);
341 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
342 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
344 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
345 if (res
== ERROR_FILE_NOT_FOUND
)
347 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
348 return TYPE_E_LIBNOTREGISTERED
;
350 else if (res
!= ERROR_SUCCESS
)
352 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
353 return TYPE_E_REGISTRYACCESS
;
358 LONG dwPathLen
= sizeof(Path
);
360 get_lcid_subkey( myLCID
, syskind
, buffer
);
362 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
366 else if (myLCID
== lcid
)
368 /* try with sub-langid */
369 myLCID
= SUBLANGID(lcid
);
371 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
373 /* try with system langid */
383 *path
= SysAllocString( Path
);
388 TRACE_(typelib
)("-- 0x%08x\n", hr
);
392 /****************************************************************************
393 * QueryPathOfRegTypeLib [OLEAUT32.164]
395 * Gets the path to a registered type library.
398 * guid [I] referenced guid
399 * wMaj [I] major version
400 * wMin [I] minor version
402 * path [O] path of typelib
406 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
407 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
410 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
414 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
419 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
422 /******************************************************************************
423 * CreateTypeLib [OLEAUT32.160] creates a typelib
429 HRESULT WINAPI
CreateTypeLib(
430 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
432 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
436 /******************************************************************************
437 * LoadTypeLib [OLEAUT32.161]
439 * Loads a type library
442 * szFile [I] Name of file to load from.
443 * pptLib [O] Pointer that receives ITypeLib object on success.
450 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
452 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
454 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
455 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
458 /******************************************************************************
459 * LoadTypeLibEx [OLEAUT32.183]
461 * Loads and optionally registers a type library
467 HRESULT WINAPI
LoadTypeLibEx(
468 LPCOLESTR szFile
, /* [in] Name of file to load from */
469 REGKIND regkind
, /* [in] Specify kind of registration */
470 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
472 WCHAR szPath
[MAX_PATH
+1];
475 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
477 if (!szFile
|| !pptLib
)
482 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
487 case REGKIND_DEFAULT
:
488 /* don't register typelibs supplied with full path. Experimentation confirms the following */
489 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
490 (szFile
[0] && (szFile
[1] == ':'))) break;
491 /* else fall-through */
493 case REGKIND_REGISTER
:
494 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
496 ITypeLib_Release(*pptLib
);
504 TRACE(" returns %08x\n",res
);
508 /******************************************************************************
509 * LoadRegTypeLib [OLEAUT32.162]
511 * Loads a registered type library.
514 * rguid [I] GUID of the registered type library.
515 * wVerMajor [I] major version.
516 * wVerMinor [I] minor version.
517 * lcid [I] locale ID.
518 * ppTLib [O] pointer that receives an ITypeLib object on success.
522 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
525 HRESULT WINAPI
LoadRegTypeLib(
537 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
541 res
= LoadTypeLib(bstr
, ppTLib
);
544 if ((wVerMajor
!=0xffff || wVerMinor
!=0xffff) && *ppTLib
)
548 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
551 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
552 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
556 ITypeLib_Release(*ppTLib
);
558 res
= TYPE_E_LIBNOTREGISTERED
;
564 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
570 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
571 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
572 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
573 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
574 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
575 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
577 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
582 static const WCHAR typelib_proxy_clsid
[] = {'{','0','0','0','2','0','4','2','4','-',
583 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
584 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
585 static const WCHAR dispatch_proxy_clsid
[] = {'{','0','0','0','2','0','4','2','0','-',
586 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
587 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
589 get_interface_key( &tattr
->guid
, keyName
);
590 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
591 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
593 const WCHAR
*proxy_clsid
;
595 if (tattr
->typekind
== TKIND_INTERFACE
|| (tattr
->wTypeFlags
& TYPEFLAG_FDUAL
))
596 proxy_clsid
= typelib_proxy_clsid
;
598 proxy_clsid
= dispatch_proxy_clsid
;
601 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
602 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
604 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
605 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
606 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
607 (const BYTE
*)proxy_clsid
, sizeof(typelib_proxy_clsid
));
611 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
612 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
613 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
614 (const BYTE
*)proxy_clsid
, sizeof(typelib_proxy_clsid
));
618 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
619 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
622 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
623 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
625 StringFromGUID2(&libattr
->guid
, buffer
, 40);
626 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
627 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
628 sprintfW(buffer
, fmtver
, libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
629 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
630 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
638 /******************************************************************************
639 * RegisterTypeLib [OLEAUT32.163]
640 * Adds information about a type library to the System Registry
642 * Docs: ITypeLib FAR * ptlib
643 * Docs: OLECHAR FAR* szFullPath
644 * Docs: OLECHAR FAR* szHelpDir
650 HRESULT WINAPI
RegisterTypeLib(
651 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
652 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
653 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
665 if (ptlib
== NULL
|| szFullPath
== NULL
)
668 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
672 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
675 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
678 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
679 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
683 /* Set the human-readable name of the typelib */
684 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
688 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
689 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
695 /* Make up the name of the typelib path subkey */
696 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
698 /* Create the typelib path subkey */
699 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
700 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
702 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
703 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
711 /* Create the flags subkey */
712 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
713 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
715 /* FIXME: is %u correct? */
716 static const WCHAR formatW
[] = {'%','u',0};
718 sprintfW(buf
, formatW
, attr
->wLibFlags
);
719 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
720 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
728 /* create the helpdir subkey */
729 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
730 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
732 BOOL freeHelpDir
= FALSE
;
735 /* if we created a new key, and helpDir was null, set the helpdir
736 to the directory which contains the typelib. However,
737 if we just opened an existing key, we leave the helpdir alone */
738 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
739 szHelpDir
= SysAllocString(szFullPath
);
740 pIndexStr
= strrchrW(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
) {
756 if (freeHelpDir
) SysFreeString(szHelpDir
);
768 /* register OLE Automation-compatible interfaces for this typelib */
769 types
= ITypeLib_GetTypeInfoCount(ptlib
);
770 for (tidx
=0; tidx
<types
; tidx
++) {
771 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
772 LPOLESTR name
= NULL
;
773 ITypeInfo
*tinfo
= NULL
;
775 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
778 case TKIND_INTERFACE
:
779 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
780 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
784 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
785 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
789 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
794 TYPEATTR
*tattr
= NULL
;
795 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
798 TRACE_(typelib
)("guid=%s, flags=%04x (",
799 debugstr_guid(&tattr
->guid
),
802 if (TRACE_ON(typelib
)) {
803 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
823 /* Register all dispinterfaces (which includes dual interfaces) and
824 oleautomation interfaces */
825 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
826 kind
== TKIND_DISPATCH
)
829 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
831 /* register interface<->typelib coupling */
832 TLB_register_interface(attr
, name
, tattr
, 0);
834 /* register TLBs into the opposite registry view, too */
835 if(opposite
== KEY_WOW64_32KEY
||
836 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
837 TLB_register_interface(attr
, name
, tattr
, opposite
);
840 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
843 ITypeInfo_Release(tinfo
);
850 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
855 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
857 WCHAR subKeyName
[50];
860 /* the path to the type */
861 get_interface_key( guid
, subKeyName
);
863 /* Delete its bits */
864 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
867 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
868 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
869 RegDeleteKeyW(subKey
, TypeLibW
);
871 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
874 /******************************************************************************
875 * UnRegisterTypeLib [OLEAUT32.186]
876 * Removes information about a type library from the System Registry
883 HRESULT WINAPI
UnRegisterTypeLib(
884 REFGUID libid
, /* [in] Guid of the library */
885 WORD wVerMajor
, /* [in] major version */
886 WORD wVerMinor
, /* [in] minor version */
887 LCID lcid
, /* [in] locale id */
890 BSTR tlibPath
= NULL
;
893 WCHAR subKeyName
[50];
896 BOOL deleteOtherStuff
;
898 TYPEATTR
* typeAttr
= NULL
;
900 ITypeInfo
* typeInfo
= NULL
;
901 ITypeLib
* typeLib
= NULL
;
904 TRACE("(IID: %s)\n",debugstr_guid(libid
));
906 /* Create the path to the key */
907 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
909 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
911 TRACE("Unsupported syskind %i\n", syskind
);
912 result
= E_INVALIDARG
;
916 /* get the path to the typelib on disk */
917 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
918 result
= E_INVALIDARG
;
922 /* Try and open the key to the type library. */
923 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
924 result
= E_INVALIDARG
;
928 /* Try and load the type library */
929 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
930 result
= TYPE_E_INVALIDSTATE
;
934 /* remove any types registered with this typelib */
935 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
936 for (i
=0; i
<numTypes
; i
++) {
937 /* get the kind of type */
938 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
942 /* skip non-interfaces, and get type info for the type */
943 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
946 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
949 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
953 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
954 kind
== TKIND_DISPATCH
)
957 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
959 TLB_unregister_interface(&typeAttr
->guid
, 0);
961 /* unregister TLBs into the opposite registry view, too */
962 if(opposite
== KEY_WOW64_32KEY
||
963 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
964 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
969 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
971 if (typeInfo
) ITypeInfo_Release(typeInfo
);
975 /* Now, delete the type library path subkey */
976 get_lcid_subkey( lcid
, syskind
, subKeyName
);
977 RegDeleteKeyW(key
, subKeyName
);
978 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
979 RegDeleteKeyW(key
, subKeyName
);
981 /* check if there is anything besides the FLAGS/HELPDIR keys.
982 If there is, we don't delete them */
983 tmpLength
= ARRAY_SIZE(subKeyName
);
984 deleteOtherStuff
= TRUE
;
986 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
987 tmpLength
= ARRAY_SIZE(subKeyName
);
989 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
990 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
991 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
992 deleteOtherStuff
= FALSE
;
996 /* only delete the other parts of the key if we're absolutely sure */
997 if (deleteOtherStuff
) {
998 RegDeleteKeyW(key
, FLAGSW
);
999 RegDeleteKeyW(key
, HELPDIRW
);
1003 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
1004 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
1005 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
1009 SysFreeString(tlibPath
);
1010 if (typeLib
) ITypeLib_Release(typeLib
);
1011 if (key
) RegCloseKey(key
);
1015 /******************************************************************************
1016 * RegisterTypeLibForUser [OLEAUT32.442]
1017 * Adds information about a type library to the user registry
1019 * Docs: ITypeLib FAR * ptlib
1020 * Docs: OLECHAR FAR* szFullPath
1021 * Docs: OLECHAR FAR* szHelpDir
1027 HRESULT WINAPI
RegisterTypeLibForUser(
1028 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
1029 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
1030 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1033 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1034 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1035 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1038 /******************************************************************************
1039 * UnRegisterTypeLibForUser [OLEAUT32.443]
1040 * Removes information about a type library from the user registry
1046 HRESULT WINAPI
UnRegisterTypeLibForUser(
1047 REFGUID libid
, /* [in] GUID of the library */
1048 WORD wVerMajor
, /* [in] major version */
1049 WORD wVerMinor
, /* [in] minor version */
1050 LCID lcid
, /* [in] locale id */
1053 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1054 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1055 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1058 /*======================= ITypeLib implementation =======================*/
1060 typedef struct tagTLBGuid
{
1067 typedef struct tagTLBCustData
1074 /* data structure for import typelibs */
1075 typedef struct tagTLBImpLib
1077 int offset
; /* offset in the file (MSFT)
1078 offset in nametable (SLTG)
1079 just used to identify library while reading
1081 TLBGuid
*guid
; /* libid */
1082 BSTR name
; /* name */
1084 LCID lcid
; /* lcid of imported typelib */
1086 WORD wVersionMajor
; /* major version number */
1087 WORD wVersionMinor
; /* minor version number */
1089 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1090 NULL if not yet loaded */
1094 typedef struct tagTLBString
{
1100 /* internal ITypeLib data */
1101 typedef struct tagITypeLibImpl
1103 ITypeLib2 ITypeLib2_iface
;
1104 ITypeComp ITypeComp_iface
;
1105 ICreateTypeLib2 ICreateTypeLib2_iface
;
1116 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1117 * exported to the application as a UNICODE string.
1119 struct list string_list
;
1120 struct list name_list
;
1121 struct list guid_list
;
1123 const TLBString
*Name
;
1124 const TLBString
*DocString
;
1125 const TLBString
*HelpFile
;
1126 const TLBString
*HelpStringDll
;
1127 DWORD dwHelpContext
;
1128 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1129 struct tagITypeInfoImpl
**typeinfos
;
1130 struct list custdata_list
;
1131 struct list implib_list
;
1132 int ctTypeDesc
; /* number of items in type desc array */
1133 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1134 library. Only used while reading MSFT
1136 struct list ref_list
; /* list of ref types in this typelib */
1137 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1140 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1146 static const ITypeLib2Vtbl tlbvt
;
1147 static const ITypeCompVtbl tlbtcvt
;
1148 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1150 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1152 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1155 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1157 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1160 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1162 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1165 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1167 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1170 /* ITypeLib methods */
1171 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1172 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1174 /*======================= ITypeInfo implementation =======================*/
1176 /* data for referenced types */
1177 typedef struct tagTLBRefType
1179 INT index
; /* Type index for internal ref or for external ref
1180 it the format is SLTG. -2 indicates to
1184 TLBGuid
*guid
; /* guid of the referenced type */
1185 /* if index == TLB_REF_USE_GUID */
1187 HREFTYPE reference
; /* The href of this ref */
1188 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1189 TLB_REF_INTERNAL for internal refs
1190 TLB_REF_NOT_FOUND for broken refs */
1195 #define TLB_REF_USE_GUID -2
1197 #define TLB_REF_INTERNAL (void*)-2
1198 #define TLB_REF_NOT_FOUND (void*)-1
1200 /* internal Parameter data */
1201 typedef struct tagTLBParDesc
1203 const TLBString
*Name
;
1204 struct list custdata_list
;
1207 /* internal Function data */
1208 typedef struct tagTLBFuncDesc
1210 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1211 const TLBString
*Name
; /* the name of this function */
1212 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1214 int HelpStringContext
;
1215 const TLBString
*HelpString
;
1216 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1217 struct list custdata_list
;
1220 /* internal Variable data */
1221 typedef struct tagTLBVarDesc
1223 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1224 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1225 const TLBString
*Name
; /* the name of this variable */
1227 int HelpStringContext
;
1228 const TLBString
*HelpString
;
1229 struct list custdata_list
;
1232 /* internal implemented interface data */
1233 typedef struct tagTLBImplType
1235 HREFTYPE hRef
; /* hRef of interface */
1236 int implflags
; /* IMPLFLAG_*s */
1237 struct list custdata_list
;
1240 /* internal TypeInfo data */
1241 typedef struct tagITypeInfoImpl
1243 ITypeInfo2 ITypeInfo2_iface
;
1244 ITypeComp ITypeComp_iface
;
1245 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1247 BOOL not_attached_to_typelib
;
1252 TYPEDESC
*tdescAlias
;
1254 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1255 int index
; /* index in this typelib; */
1256 HREFTYPE hreftype
; /* hreftype for app object binding */
1257 /* type libs seem to store the doc strings in ascii
1258 * so why should we do it in unicode?
1260 const TLBString
*Name
;
1261 const TLBString
*DocString
;
1262 const TLBString
*DllName
;
1263 const TLBString
*Schema
;
1264 DWORD dwHelpContext
;
1265 DWORD dwHelpStringContext
;
1268 TLBFuncDesc
*funcdescs
;
1271 TLBVarDesc
*vardescs
;
1273 /* Implemented Interfaces */
1274 TLBImplType
*impltypes
;
1276 struct list
*pcustdata_list
;
1277 struct list custdata_list
;
1280 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1282 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1285 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1287 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1290 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1292 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1295 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1297 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1300 static const ITypeInfo2Vtbl tinfvt
;
1301 static const ITypeCompVtbl tcompvt
;
1302 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1304 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1305 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1307 typedef struct tagTLBContext
1309 unsigned int oStart
; /* start of TLB in file */
1310 unsigned int pos
; /* current pos */
1311 unsigned int length
; /* total length */
1312 void *mapping
; /* memory mapping */
1313 MSFT_SegDir
* pTblDir
;
1314 ITypeLibImpl
* pLibInfo
;
1318 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1320 return str
!= NULL
? str
->str
: NULL
;
1323 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1327 return memcmp(left
, str
->str
, len
);
1330 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1332 return guid
!= NULL
? &guid
->guid
: NULL
;
1335 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1337 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1340 static int get_ptr_size(SYSKIND syskind
)
1350 WARN("Unhandled syskind: 0x%x\n", syskind
);
1357 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1358 if (pTD
->vt
& VT_RESERVED
)
1359 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1360 if (pTD
->vt
& VT_BYREF
)
1361 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1362 if (pTD
->vt
& VT_ARRAY
)
1363 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1364 if (pTD
->vt
& VT_VECTOR
)
1365 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1366 switch(pTD
->vt
& VT_TYPEMASK
) {
1367 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1368 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1369 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1370 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1371 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1372 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1373 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1374 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1375 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1376 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1377 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1378 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1379 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1380 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1381 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1382 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1383 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1384 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1385 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1386 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1387 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1388 pTD
->u
.hreftype
); break;
1389 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1390 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1391 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1392 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1394 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1395 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1397 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1398 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1399 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1402 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1406 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1408 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1409 dump_TypeDesc(&edesc
->tdesc
,buf
);
1410 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1411 MESSAGE("\t\tu.paramdesc.wParamFlags");
1412 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1413 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1414 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1415 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1416 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1417 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1418 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1419 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1420 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1422 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1424 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1425 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1426 MESSAGE("Param %d:\n",i
);
1427 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1429 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1430 switch (funcdesc
->funckind
) {
1431 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1432 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1433 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1434 case FUNC_STATIC
: MESSAGE("static");break;
1435 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1436 default: MESSAGE("unknown");break;
1438 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1439 switch (funcdesc
->invkind
) {
1440 case INVOKE_FUNC
: MESSAGE("func");break;
1441 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1442 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1443 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1445 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1446 switch (funcdesc
->callconv
) {
1447 case CC_CDECL
: MESSAGE("cdecl");break;
1448 case CC_PASCAL
: MESSAGE("pascal");break;
1449 case CC_STDCALL
: MESSAGE("stdcall");break;
1450 case CC_SYSCALL
: MESSAGE("syscall");break;
1453 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1454 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1455 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1457 MESSAGE("\telemdescFunc (return value type):\n");
1458 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1461 static const char * const typekind_desc
[] =
1474 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1477 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1478 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1479 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1482 dump_FUNCDESC(&(pfd
->funcdesc
));
1484 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1485 if(pfd
->Entry
== NULL
)
1486 MESSAGE("\tentry: (null)\n");
1487 else if(pfd
->Entry
== (void*)-1)
1488 MESSAGE("\tentry: invalid\n");
1489 else if(IS_INTRESOURCE(pfd
->Entry
))
1490 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1492 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1494 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1498 dump_TLBFuncDescOne(pfd
);
1503 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1507 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1513 static void dump_TLBImpLib(const TLBImpLib
*import
)
1515 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1516 debugstr_w(import
->name
));
1517 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1518 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1521 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1525 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1527 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1528 if(ref
->index
== -1)
1529 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1531 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1533 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1535 TRACE_(typelib
)("in lib\n");
1536 dump_TLBImpLib(ref
->pImpTLInfo
);
1541 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1546 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1547 impl
->hRef
, impl
->implflags
);
1553 static void dump_DispParms(const DISPPARAMS
* pdp
)
1557 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1559 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1561 TRACE("named args:\n");
1562 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1563 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1566 if (pdp
->cArgs
&& pdp
->rgvarg
)
1569 for (index
= 0; index
< pdp
->cArgs
; index
++)
1570 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1574 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1576 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1577 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1578 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1579 TRACE("kind:%s\n", typekind_desc
[pty
->typeattr
.typekind
]);
1580 TRACE("fct:%u var:%u impl:%u\n", pty
->typeattr
.cFuncs
, pty
->typeattr
.cVars
, pty
->typeattr
.cImplTypes
);
1581 TRACE("wTypeFlags: 0x%04x\n", pty
->typeattr
.wTypeFlags
);
1582 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1583 if (pty
->typeattr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1585 dump_TLBFuncDesc(pty
->funcdescs
, pty
->typeattr
.cFuncs
);
1586 dump_TLBVarDesc(pty
->vardescs
, pty
->typeattr
.cVars
);
1587 dump_TLBImplType(pty
->impltypes
, pty
->typeattr
.cImplTypes
);
1590 static void dump_VARDESC(const VARDESC
*v
)
1592 MESSAGE("memid %d\n",v
->memid
);
1593 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1594 MESSAGE("oInst %d\n",v
->u
.oInst
);
1595 dump_ELEMDESC(&(v
->elemdescVar
));
1596 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1597 MESSAGE("varkind %d\n",v
->varkind
);
1600 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1602 /* VT_LPWSTR is largest type that, may appear in type description */
1603 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1604 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1605 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1606 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1607 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1608 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1609 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1610 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1613 static void TLB_abort(void)
1618 /* returns the size required for a deep copy of a typedesc into a
1620 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1624 if (alloc_initial_space
)
1625 size
+= sizeof(TYPEDESC
);
1631 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1634 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1635 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1641 /* deep copy a typedesc into a flat buffer */
1642 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1647 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1656 dest
->u
.lptdesc
= buffer
;
1657 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1660 dest
->u
.lpadesc
= buffer
;
1661 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1662 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1663 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1669 /* free custom data allocated by MSFT_CustData */
1670 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1672 TLBCustData
*cd
, *cdn
;
1673 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1675 list_remove(&cd
->entry
);
1676 VariantClear(&cd
->data
);
1681 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1686 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1687 ret
= SysAllocStringLen(NULL
, len
- 1);
1688 if (!ret
) return ret
;
1689 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1693 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1694 UINT n
, MEMBERID memid
)
1697 if(funcdescs
->funcdesc
.memid
== memid
)
1705 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1706 UINT n
, MEMBERID memid
)
1709 if(vardescs
->vardesc
.memid
== memid
)
1717 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1718 UINT n
, const OLECHAR
*name
)
1721 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1729 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1731 TLBCustData
*cust_data
;
1732 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1733 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1738 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1739 UINT n
, const OLECHAR
*name
)
1742 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1750 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1752 list_init(&var_desc
->custdata_list
);
1755 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1759 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1764 TLBVarDesc_Constructor(&ret
[n
-1]);
1771 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1775 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1780 list_init(&ret
[n
-1].custdata_list
);
1787 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1789 list_init(&func_desc
->custdata_list
);
1792 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1796 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1801 TLBFuncDesc_Constructor(&ret
[n
-1]);
1808 static void TLBImplType_Constructor(TLBImplType
*impl
)
1810 list_init(&impl
->custdata_list
);
1813 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1817 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1822 TLBImplType_Constructor(&ret
[n
-1]);
1829 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1830 const GUID
*new_guid
, HREFTYPE hreftype
)
1834 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1835 if (IsEqualGUID(&guid
->guid
, new_guid
))
1839 guid
= heap_alloc(sizeof(TLBGuid
));
1843 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1844 guid
->hreftype
= hreftype
;
1846 list_add_tail(guid_list
, &guid
->entry
);
1851 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1853 TLBCustData
*cust_data
;
1865 return DISP_E_BADVARTYPE
;
1868 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1871 cust_data
= heap_alloc(sizeof(TLBCustData
));
1873 return E_OUTOFMEMORY
;
1875 cust_data
->guid
= tlbguid
;
1876 VariantInit(&cust_data
->data
);
1878 list_add_tail(custdata_list
, &cust_data
->entry
);
1880 VariantClear(&cust_data
->data
);
1882 return VariantCopy(&cust_data
->data
, var
);
1885 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1892 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1893 if (strcmpW(str
->str
, new_str
) == 0)
1897 str
= heap_alloc(sizeof(TLBString
));
1901 str
->str
= SysAllocString(new_str
);
1907 list_add_tail(string_list
, &str
->entry
);
1912 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1913 ULONG
*size
, WORD
*align
)
1919 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1923 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1925 ITypeInfo_Release(other
);
1930 *size
= attr
->cbSizeInstance
;
1932 *align
= attr
->cbAlignment
;
1934 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1935 ITypeInfo_Release(other
);
1940 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1941 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1943 ULONG i
, sub
, ptr_size
;
1946 ptr_size
= get_ptr_size(sys
);
1985 *size
= sizeof(DATE
);
1988 *size
= sizeof(VARIANT
);
1990 if(sys
== SYS_WIN32
)
1991 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1995 *size
= sizeof(DECIMAL
);
2002 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2003 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2004 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2009 case VT_USERDEFINED
:
2010 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2012 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2026 /**********************************************************************
2028 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2031 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2033 if (where
!= DO_NOT_SEEK
)
2035 where
+= pcx
->oStart
;
2036 if (where
> pcx
->length
)
2039 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2047 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2049 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2050 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2052 MSFT_Seek(pcx
, where
);
2053 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2054 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2059 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2064 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2065 FromLEDWords(buffer
, ret
);
2070 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2075 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2076 FromLEWords(buffer
, ret
);
2081 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2084 MSFT_GuidEntry entry
;
2087 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2089 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2092 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2094 guid
= heap_alloc(sizeof(TLBGuid
));
2096 guid
->offset
= offs
;
2097 guid
->guid
= entry
.guid
;
2098 guid
->hreftype
= entry
.hreftype
;
2100 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2102 offs
+= sizeof(MSFT_GuidEntry
);
2106 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2110 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2111 if(ret
->offset
== offset
){
2112 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2120 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2122 MSFT_NameIntro niName
;
2126 ERR_(typelib
)("bad offset %d\n", offset
);
2130 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2131 pcx
->pTblDir
->pNametab
.offset
+offset
);
2133 return niName
.hreftype
;
2136 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2139 MSFT_NameIntro intro
;
2141 int offs
= 0, lengthInChars
;
2143 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2147 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2150 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2151 intro
.namelen
&= 0xFF;
2152 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2154 len_piece
= (len_piece
+ 4) & ~0x3;
2158 string
= heap_alloc(len_piece
+ 1);
2159 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2160 string
[intro
.namelen
] = '\0';
2162 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2163 string
, -1, NULL
, 0);
2164 if (!lengthInChars
) {
2166 return E_UNEXPECTED
;
2169 tlbstr
= heap_alloc(sizeof(TLBString
));
2171 tlbstr
->offset
= offs
;
2172 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2173 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2177 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2183 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2187 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2188 if (tlbstr
->offset
== offset
) {
2189 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2197 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2201 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2202 if (tlbstr
->offset
== offset
) {
2203 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2212 * read a value and fill a VARIANT structure
2214 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2218 TRACE_(typelib
)("\n");
2220 if(offset
<0) { /* data are packed in here */
2221 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2222 V_I4(pVar
) = offset
& 0x3ffffff;
2225 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2226 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2227 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2228 switch (V_VT(pVar
)){
2229 case VT_EMPTY
: /* FIXME: is this right? */
2230 case VT_NULL
: /* FIXME: is this right? */
2231 case VT_I2
: /* this should not happen */
2242 case VT_VOID
: /* FIXME: is this right? */
2250 case VT_DECIMAL
: /* FIXME: is this right? */
2253 /* pointer types with known behaviour */
2256 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2258 V_BSTR(pVar
) = NULL
;
2260 ptr
= heap_alloc_zero(size
);
2261 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2262 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2263 /* FIXME: do we need a AtoW conversion here? */
2264 V_UNION(pVar
, bstrVal
[size
])='\0';
2265 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2270 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2277 case VT_USERDEFINED
:
2283 case VT_STREAMED_OBJECT
:
2284 case VT_STORED_OBJECT
:
2285 case VT_BLOB_OBJECT
:
2290 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2294 if(size
>0) /* (big|small) endian correct? */
2295 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2299 * create a linked list with custom data
2301 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2307 TRACE_(typelib
)("\n");
2309 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2313 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2314 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2315 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2316 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2317 list_add_head(custdata_list
, &pNew
->entry
);
2318 offset
= entry
.next
;
2323 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2326 pTd
->vt
=type
& VT_TYPEMASK
;
2328 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2330 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2333 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2335 return (invkind
== INVOKE_PROPERTYGET
||
2336 invkind
== INVOKE_PROPERTYPUT
||
2337 invkind
== INVOKE_PROPERTYPUTREF
);
2341 MSFT_DoFuncs(TLBContext
* pcx
,
2346 TLBFuncDesc
** pptfd
)
2349 * member information is stored in a data structure at offset
2350 * indicated by the memoffset field of the typeinfo structure
2351 * There are several distinctive parts.
2352 * The first part starts with a field that holds the total length
2353 * of this (first) part excluding this field. Then follow the records,
2354 * for each member there is one record.
2356 * The first entry is always the length of the record (including this
2358 * The rest of the record depends on the type of the member. If there is
2359 * a field indicating the member type (function, variable, interface, etc)
2360 * I have not found it yet. At this time we depend on the information
2361 * in the type info and the usual order how things are stored.
2363 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2366 * Third is an equal sized array with file offsets to the name entry
2369 * The fourth and last (?) part is an array with offsets to the records
2370 * in the first part of this file segment.
2373 int infolen
, nameoffset
, reclength
, i
;
2374 int recoffset
= offset
+ sizeof(INT
);
2376 char *recbuf
= heap_alloc(0xffff);
2377 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2378 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2380 TRACE_(typelib
)("\n");
2382 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2384 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2386 for ( i
= 0; i
< cFuncs
; i
++ )
2390 /* name, eventually add to a hash table */
2391 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2392 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2394 /* read the function information record */
2395 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2397 reclength
&= 0xffff;
2399 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2401 /* size without argument data */
2402 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2403 if (pFuncRec
->FKCCIC
& 0x1000)
2404 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2406 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2407 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2409 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2410 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2412 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2414 if (pFuncRec
->FKCCIC
& 0x2000 )
2416 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2417 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2418 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2421 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2424 ptfd
->Entry
= (TLBString
*)-1;
2426 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2427 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2429 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2430 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2432 /* fill the FuncDesc Structure */
2433 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2434 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2436 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2437 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2438 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2439 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2440 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2441 ptfd
->funcdesc
.oVft
= (pFuncRec
->VtableOffset
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
2442 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2444 /* nameoffset is sometimes -1 on the second half of a propget/propput
2445 * pair of functions */
2446 if ((nameoffset
== -1) && (i
> 0) &&
2447 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2448 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2449 ptfd
->Name
= ptfd_prev
->Name
;
2451 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2455 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2457 /* do the parameters/arguments */
2458 if(pFuncRec
->nrargs
)
2461 MSFT_ParameterInfo paraminfo
;
2463 ptfd
->funcdesc
.lprgelemdescParam
=
2464 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2466 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2468 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2469 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2471 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2473 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2479 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2482 if (paraminfo
.oName
!= -1)
2483 ptfd
->pParamDesc
[j
].Name
=
2484 MSFT_ReadName( pcx
, paraminfo
.oName
);
2485 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2488 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2489 (pFuncRec
->FKCCIC
& 0x1000) )
2491 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2493 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2495 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2497 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2498 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2500 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2504 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2507 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2508 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2509 pFuncRec
->FKCCIC
& 0x80 )
2512 pFuncRec
->oArgCustData
[j
],
2513 &ptfd
->pParamDesc
[j
].custdata_list
);
2516 /* SEEK value = jump to offset,
2517 * from there jump to the end of record,
2518 * go back by (j-1) arguments
2520 MSFT_ReadLEDWords( ¶minfo
,
2521 sizeof(MSFT_ParameterInfo
), pcx
,
2522 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2523 * sizeof(MSFT_ParameterInfo
)));
2527 /* scode is not used: archaic win16 stuff FIXME: right? */
2528 ptfd
->funcdesc
.cScodes
= 0 ;
2529 ptfd
->funcdesc
.lprgscode
= NULL
;
2533 recoffset
+= reclength
;
2538 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2539 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2541 int infolen
, nameoffset
, reclength
;
2543 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2548 TRACE_(typelib
)("\n");
2550 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2551 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2552 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2553 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2554 recoffset
+= offset
+sizeof(INT
);
2555 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2556 /* name, eventually add to a hash table */
2557 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2558 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2559 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2560 /* read the variable information record */
2561 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2563 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2566 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2567 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2569 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2570 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2572 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2573 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2575 /* fill the VarDesc Structure */
2576 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2577 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2578 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2579 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2580 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2581 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2582 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2583 if(pVarRec
->VarKind
== VAR_CONST
){
2584 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2585 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2586 pVarRec
->OffsValue
, pcx
);
2588 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2589 recoffset
+= reclength
;
2593 /* process Implemented Interfaces of a com class */
2594 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2598 MSFT_RefRecord refrec
;
2601 TRACE_(typelib
)("\n");
2603 pTI
->impltypes
= TLBImplType_Alloc(count
);
2604 pImpl
= pTI
->impltypes
;
2605 for(i
=0;i
<count
;i
++){
2606 if(offset
<0) break; /* paranoia */
2607 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2608 pImpl
->hRef
= refrec
.reftype
;
2609 pImpl
->implflags
=refrec
.flags
;
2610 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2611 offset
=refrec
.onext
;
2617 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2618 * and some structures, and fix the alignment */
2619 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2621 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2622 switch(info
->tdescAlias
->vt
){
2630 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2631 info
->typeattr
.cbAlignment
= sizeof(void*);
2634 case VT_USERDEFINED
:
2635 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2638 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2639 info
->typeattr
.cbAlignment
= 8;
2641 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2642 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2644 info
->typeattr
.cbAlignment
= sizeof(void*);
2647 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2648 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2649 info
->typeattr
.typekind
== TKIND_COCLASS
){
2650 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2651 info
->typeattr
.cbAlignment
= sizeof(void*);
2657 * process a typeinfo record
2659 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2662 ITypeLibImpl
* pLibInfo
)
2664 MSFT_TypeInfoBase tiBase
;
2665 ITypeInfoImpl
*ptiRet
;
2667 TRACE_(typelib
)("count=%u\n", count
);
2669 ptiRet
= ITypeInfoImpl_Constructor();
2670 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2671 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2673 /* this is where we are coming from */
2674 ptiRet
->pTypeLib
= pLibInfo
;
2675 ptiRet
->index
=count
;
2677 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2678 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2679 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2680 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2681 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2682 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2683 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2684 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2685 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2686 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2687 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2688 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2689 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
;
2690 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2692 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2693 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2694 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2698 /* IDLDESC idldescType; *//* never saw this one != zero */
2700 /* name, eventually add to a hash table */
2701 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2702 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2703 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2705 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2706 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2707 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2709 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2710 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2712 /* note: InfoType's Help file and HelpStringDll come from the containing
2713 * library. Further HelpString and Docstring appear to be the same thing :(
2716 if(ptiRet
->typeattr
.cFuncs
>0 )
2717 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2718 ptiRet
->typeattr
.cVars
,
2719 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2721 if(ptiRet
->typeattr
.cVars
>0 )
2722 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2723 ptiRet
->typeattr
.cVars
,
2724 tiBase
.memoffset
, &ptiRet
->vardescs
);
2725 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2726 switch(ptiRet
->typeattr
.typekind
)
2729 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2732 case TKIND_DISPATCH
:
2733 /* This is not -1 when the interface is a non-base dual interface or
2734 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2735 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2739 if (tiBase
.datatype1
!= -1)
2741 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2742 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2746 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2747 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2751 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2753 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2754 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2755 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2756 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2757 if (TRACE_ON(typelib
))
2758 dump_TypeInfo(ptiRet
);
2763 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2766 INT16 len_str
, len_piece
;
2767 int offs
= 0, lengthInChars
;
2769 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2773 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2776 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2777 len_piece
= len_str
+ sizeof(INT16
);
2779 len_piece
= (len_piece
+ 4) & ~0x3;
2783 string
= heap_alloc(len_piece
+ 1);
2784 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2785 string
[len_str
] = '\0';
2787 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2788 string
, -1, NULL
, 0);
2789 if (!lengthInChars
) {
2791 return E_UNEXPECTED
;
2794 tlbstr
= heap_alloc(sizeof(TLBString
));
2796 tlbstr
->offset
= offs
;
2797 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2798 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2802 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2808 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2813 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2814 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2815 MSFT_ImpInfo impinfo
;
2818 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2820 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2821 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2823 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2824 if(pImpLib
->offset
==impinfo
.oImpFile
)
2827 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2828 ref
->reference
= offs
;
2829 ref
->pImpTLInfo
= pImpLib
;
2830 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2831 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2832 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2833 ref
->index
= TLB_REF_USE_GUID
;
2835 ref
->index
= impinfo
.oGuid
;
2837 ERR("Cannot find a reference\n");
2838 ref
->reference
= -1;
2839 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2842 offs
+= sizeof(impinfo
);
2848 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2849 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2850 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2853 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2854 static CRITICAL_SECTION cache_section
;
2855 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2857 0, 0, &cache_section
,
2858 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2859 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2861 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2864 typedef struct TLB_PEFile
2866 IUnknown IUnknown_iface
;
2869 HRSRC typelib_resource
;
2870 HGLOBAL typelib_global
;
2871 LPVOID typelib_base
;
2874 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2876 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2879 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2881 if (IsEqualIID(riid
, &IID_IUnknown
))
2884 IUnknown_AddRef(iface
);
2888 return E_NOINTERFACE
;
2891 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2893 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2894 return InterlockedIncrement(&This
->refs
);
2897 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2899 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2900 ULONG refs
= InterlockedDecrement(&This
->refs
);
2903 if (This
->typelib_global
)
2904 FreeResource(This
->typelib_global
);
2906 FreeLibrary(This
->dll
);
2912 static const IUnknownVtbl TLB_PEFile_Vtable
=
2914 TLB_PEFile_QueryInterface
,
2919 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2922 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2924 This
= heap_alloc(sizeof(TLB_PEFile
));
2926 return E_OUTOFMEMORY
;
2928 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2931 This
->typelib_resource
= NULL
;
2932 This
->typelib_global
= NULL
;
2933 This
->typelib_base
= NULL
;
2935 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2936 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2940 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2941 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2942 if (This
->typelib_resource
)
2944 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2945 if (This
->typelib_global
)
2947 This
->typelib_base
= LockResource(This
->typelib_global
);
2949 if (This
->typelib_base
)
2951 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2952 *ppBase
= This
->typelib_base
;
2953 *ppFile
= &This
->IUnknown_iface
;
2959 TRACE("No TYPELIB resource found\n");
2963 TLB_PEFile_Release(&This
->IUnknown_iface
);
2967 typedef struct TLB_NEFile
2969 IUnknown IUnknown_iface
;
2971 LPVOID typelib_base
;
2974 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2976 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2979 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2981 if (IsEqualIID(riid
, &IID_IUnknown
))
2984 IUnknown_AddRef(iface
);
2988 return E_NOINTERFACE
;
2991 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2993 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2994 return InterlockedIncrement(&This
->refs
);
2997 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2999 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3000 ULONG refs
= InterlockedDecrement(&This
->refs
);
3003 heap_free(This
->typelib_base
);
3009 static const IUnknownVtbl TLB_NEFile_Vtable
=
3011 TLB_NEFile_QueryInterface
,
3016 /***********************************************************************
3017 * read_xx_header [internal]
3019 static int read_xx_header( HFILE lzfd
)
3021 IMAGE_DOS_HEADER mzh
;
3024 LZSeek( lzfd
, 0, SEEK_SET
);
3025 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3027 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3030 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3031 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3034 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3036 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3037 return IMAGE_OS2_SIGNATURE
;
3038 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3039 return IMAGE_NT_SIGNATURE
;
3042 WARN("Can't handle %s files.\n", magic
);
3047 /***********************************************************************
3048 * find_ne_resource [internal]
3050 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3051 DWORD
*resLen
, DWORD
*resOff
)
3053 IMAGE_OS2_HEADER nehd
;
3054 NE_TYPEINFO
*typeInfo
;
3055 NE_NAMEINFO
*nameInfo
;
3061 /* Read in NE header */
3062 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3063 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3065 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3068 TRACE("No resources in NE dll\n" );
3072 /* Read in resource table */
3073 resTab
= heap_alloc( resTabSize
);
3074 if ( !resTab
) return FALSE
;
3076 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3077 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3079 heap_free( resTab
);
3084 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3086 if (!IS_INTRESOURCE(typeid)) /* named type */
3088 BYTE len
= strlen( typeid );
3089 while (typeInfo
->type_id
)
3091 if (!(typeInfo
->type_id
& 0x8000))
3093 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3094 if ((*p
== len
) && !_strnicmp( (char*)p
+1, typeid, len
)) goto found_type
;
3096 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3097 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3100 else /* numeric type id */
3102 WORD id
= LOWORD(typeid) | 0x8000;
3103 while (typeInfo
->type_id
)
3105 if (typeInfo
->type_id
== id
) goto found_type
;
3106 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3107 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3110 TRACE("No typeid entry found for %p\n", typeid );
3111 heap_free( resTab
);
3115 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3117 if (!IS_INTRESOURCE(resid
)) /* named resource */
3119 BYTE len
= strlen( resid
);
3120 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3122 BYTE
*p
= resTab
+ nameInfo
->id
;
3123 if (nameInfo
->id
& 0x8000) continue;
3124 if ((*p
== len
) && !_strnicmp( (char*)p
+1, resid
, len
)) goto found_name
;
3127 else /* numeric resource id */
3129 WORD id
= LOWORD(resid
) | 0x8000;
3130 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3131 if (nameInfo
->id
== id
) goto found_name
;
3133 TRACE("No resid entry found for %p\n", typeid );
3134 heap_free( resTab
);
3138 /* Return resource data */
3139 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3140 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3142 heap_free( resTab
);
3146 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3150 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3153 This
= heap_alloc(sizeof(TLB_NEFile
));
3154 if (!This
) return E_OUTOFMEMORY
;
3156 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3158 This
->typelib_base
= NULL
;
3160 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3161 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3163 DWORD reslen
, offset
;
3164 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3166 This
->typelib_base
= heap_alloc(reslen
);
3167 if( !This
->typelib_base
)
3171 LZSeek( lzfd
, offset
, SEEK_SET
);
3172 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3174 *ppBase
= This
->typelib_base
;
3175 *pdwTLBLength
= reslen
;
3176 *ppFile
= &This
->IUnknown_iface
;
3182 if( lzfd
>= 0) LZClose( lzfd
);
3183 TLB_NEFile_Release(&This
->IUnknown_iface
);
3187 typedef struct TLB_Mapping
3189 IUnknown IUnknown_iface
;
3193 LPVOID typelib_base
;
3196 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3198 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3201 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3203 if (IsEqualIID(riid
, &IID_IUnknown
))
3206 IUnknown_AddRef(iface
);
3210 return E_NOINTERFACE
;
3213 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3215 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3216 return InterlockedIncrement(&This
->refs
);
3219 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3221 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3222 ULONG refs
= InterlockedDecrement(&This
->refs
);
3225 if (This
->typelib_base
)
3226 UnmapViewOfFile(This
->typelib_base
);
3228 CloseHandle(This
->mapping
);
3229 if (This
->file
!= INVALID_HANDLE_VALUE
)
3230 CloseHandle(This
->file
);
3236 static const IUnknownVtbl TLB_Mapping_Vtable
=
3238 TLB_Mapping_QueryInterface
,
3243 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3247 This
= heap_alloc(sizeof(TLB_Mapping
));
3249 return E_OUTOFMEMORY
;
3251 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3253 This
->file
= INVALID_HANDLE_VALUE
;
3254 This
->mapping
= NULL
;
3255 This
->typelib_base
= NULL
;
3257 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3258 if (INVALID_HANDLE_VALUE
!= This
->file
)
3260 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3263 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3264 if(This
->typelib_base
)
3266 /* retrieve file size */
3267 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3268 *ppBase
= This
->typelib_base
;
3269 *ppFile
= &This
->IUnknown_iface
;
3275 IUnknown_Release(&This
->IUnknown_iface
);
3276 return TYPE_E_CANTLOADLIBRARY
;
3279 /****************************************************************************
3282 * find the type of the typelib file and map the typelib resource into
3286 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3287 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3289 ITypeLibImpl
*entry
;
3292 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3293 LPVOID pBase
= NULL
;
3294 DWORD dwTLBLength
= 0;
3295 IUnknown
*pFile
= NULL
;
3300 index_str
= strrchrW(pszFileName
, '\\');
3301 if(index_str
&& *++index_str
!= '\0')
3304 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3305 if(*end_ptr
== '\0')
3307 int str_len
= index_str
- pszFileName
- 1;
3309 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3310 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3315 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3317 if(strchrW(file
, '\\'))
3319 lstrcpyW(pszPath
, file
);
3323 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3324 pszPath
[len
] = '\\';
3325 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3329 if(file
!= pszFileName
) heap_free(file
);
3331 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3332 if(h
!= INVALID_HANDLE_VALUE
){
3333 FILE_NAME_INFORMATION size_info
;
3336 /* GetFileInformationByHandleEx returns the path of the file without
3337 * WOW64 redirection */
3338 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, &size_info
, sizeof(size_info
));
3339 if(br
|| GetLastError() == ERROR_MORE_DATA
){
3340 FILE_NAME_INFORMATION
*info
;
3341 DWORD size
= sizeof(*info
) + size_info
.FileNameLength
+ sizeof(WCHAR
);
3343 info
= HeapAlloc(GetProcessHeap(), 0, size
);
3345 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, info
, size
);
3347 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3348 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3351 HeapFree(GetProcessHeap(), 0, info
);
3357 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3359 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3360 EnterCriticalSection(&cache_section
);
3361 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3363 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3365 TRACE("cache hit\n");
3366 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3367 ITypeLib2_AddRef(*ppTypeLib
);
3368 LeaveCriticalSection(&cache_section
);
3372 LeaveCriticalSection(&cache_section
);
3374 /* now actually load and parse the typelib */
3376 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3377 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3378 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3379 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3380 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3383 if (dwTLBLength
>= 4)
3385 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3386 if (dwSignature
== MSFT_SIGNATURE
)
3387 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3388 else if (dwSignature
== SLTG_SIGNATURE
)
3389 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3392 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3393 ret
= TYPE_E_CANTLOADLIBRARY
;
3397 ret
= TYPE_E_CANTLOADLIBRARY
;
3398 IUnknown_Release(pFile
);
3402 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3404 TRACE("adding to cache\n");
3405 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3406 lstrcpyW(impl
->path
, pszPath
);
3407 /* We should really canonicalise the path here. */
3408 impl
->index
= index
;
3410 /* FIXME: check if it has added already in the meantime */
3411 EnterCriticalSection(&cache_section
);
3412 list_add_head(&tlb_cache
, &impl
->entry
);
3413 LeaveCriticalSection(&cache_section
);
3419 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3421 ret
= TYPE_E_CANTLOADLIBRARY
;
3428 /*================== ITypeLib(2) Methods ===================================*/
3430 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3432 ITypeLibImpl
* pTypeLibImpl
;
3434 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3435 if (!pTypeLibImpl
) return NULL
;
3437 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3438 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3439 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3440 pTypeLibImpl
->ref
= 1;
3442 list_init(&pTypeLibImpl
->implib_list
);
3443 list_init(&pTypeLibImpl
->custdata_list
);
3444 list_init(&pTypeLibImpl
->name_list
);
3445 list_init(&pTypeLibImpl
->string_list
);
3446 list_init(&pTypeLibImpl
->guid_list
);
3447 list_init(&pTypeLibImpl
->ref_list
);
3448 pTypeLibImpl
->dispatch_href
= -1;
3450 return pTypeLibImpl
;
3453 /****************************************************************************
3454 * ITypeLib2_Constructor_MSFT
3456 * loading an MSFT typelib from an in-memory image
3458 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3462 MSFT_Header tlbHeader
;
3463 MSFT_SegDir tlbSegDir
;
3464 ITypeLibImpl
* pTypeLibImpl
;
3467 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3469 pTypeLibImpl
= TypeLibImpl_Constructor();
3470 if (!pTypeLibImpl
) return NULL
;
3472 /* get pointer to beginning of typelib data */
3476 cx
.pLibInfo
= pTypeLibImpl
;
3477 cx
.length
= dwTLBLength
;
3480 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3481 TRACE_(typelib
)("header:\n");
3482 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3483 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3484 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3487 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3489 /* there is a small amount of information here until the next important
3491 * the segment directory . Try to calculate the amount of data */
3492 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3494 /* now read the segment directory */
3495 TRACE("read segment directory (at %d)\n",lPSegDir
);
3496 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3497 cx
.pTblDir
= &tlbSegDir
;
3499 /* just check two entries */
3500 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3502 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3503 heap_free(pTypeLibImpl
);
3507 MSFT_ReadAllNames(&cx
);
3508 MSFT_ReadAllStrings(&cx
);
3509 MSFT_ReadAllGuids(&cx
);
3511 /* now fill our internal data */
3512 /* TLIBATTR fields */
3513 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3515 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3516 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3517 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3518 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3519 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3521 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3522 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3524 /* name, eventually add to a hash table */
3525 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3528 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3529 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3531 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3534 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3535 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3538 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3541 if(tlbHeader
.CustomDataOffset
>= 0)
3543 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3546 /* fill in type descriptions */
3547 if(tlbSegDir
.pTypdescTab
.length
> 0)
3549 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3551 pTypeLibImpl
->ctTypeDesc
= cTD
;
3552 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3553 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3556 /* FIXME: add several sanity checks here */
3557 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3558 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3560 /* FIXME: check safearray */
3562 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3564 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3566 else if(td
[0] == VT_CARRAY
)
3568 /* array descr table here */
3569 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3571 else if(td
[0] == VT_USERDEFINED
)
3573 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3575 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3578 /* second time around to fill the array subscript info */
3581 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3582 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3584 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3585 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3588 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3590 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3592 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3594 for(j
= 0; j
<td
[2]; j
++)
3596 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3597 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3598 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3599 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3604 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3605 ERR("didn't find array description data\n");
3610 /* imported type libs */
3611 if(tlbSegDir
.pImpFiles
.offset
>0)
3614 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3617 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3621 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3622 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3623 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3625 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3626 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3627 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3628 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3631 name
= heap_alloc_zero(size
+1);
3632 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3633 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3636 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3637 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3639 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3643 MSFT_ReadAllRefs(&cx
);
3645 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3648 if(tlbHeader
.nrtypeinfos
>= 0 )
3650 ITypeInfoImpl
**ppTI
;
3652 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3654 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3656 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3659 (pTypeLibImpl
->TypeInfoCount
)++;
3664 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3665 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3666 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3670 TRACE("(%p)\n", pTypeLibImpl
);
3671 return &pTypeLibImpl
->ITypeLib2_iface
;
3675 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3681 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3682 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3686 guid
->Data4
[0] = s
>> 8;
3687 guid
->Data4
[1] = s
& 0xff;
3690 for(i
= 0; i
< 6; i
++) {
3691 memcpy(b
, str
+ 24 + 2 * i
, 2);
3692 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3697 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3704 bytelen
= *(const WORD
*)ptr
;
3705 if(bytelen
== 0xffff) return 2;
3707 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3708 tmp_str
= SysAllocStringLen(NULL
, len
);
3710 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3711 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3712 SysFreeString(tmp_str
);
3717 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3722 bytelen
= *(const WORD
*)ptr
;
3723 if(bytelen
== 0xffff) return 2;
3724 *str
= heap_alloc(bytelen
+ 1);
3725 memcpy(*str
, ptr
+ 2, bytelen
);
3726 (*str
)[bytelen
] = '\0';
3730 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3735 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3736 if (tlbstr
->offset
== offset
)
3740 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3741 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3742 SysFreeString(tmp_str
);
3747 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3749 char *ptr
= pLibBlk
;
3752 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3753 FIXME("libblk magic = %04x\n", w
);
3758 if((w
= *(WORD
*)ptr
) != 0xffff) {
3759 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3764 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3766 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3768 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3771 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3772 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3775 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3776 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3778 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3781 ptr
+= 4; /* skip res12 */
3783 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3786 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3789 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3792 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3793 ptr
+= sizeof(GUID
);
3795 return ptr
- (char*)pLibBlk
;
3798 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3803 } sltg_ref_lookup_t
;
3805 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3806 HREFTYPE
*typelib_ref
)
3808 if(table
&& typeinfo_ref
< table
->num
)
3810 *typelib_ref
= table
->refs
[typeinfo_ref
];
3814 ERR_(typelib
)("Unable to find reference\n");
3819 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3824 if((*pType
& 0xe00) == 0xe00) {
3826 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3827 pTD
= pTD
->u
.lptdesc
;
3829 switch(*pType
& 0x3f) {
3832 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3833 pTD
= pTD
->u
.lptdesc
;
3836 case VT_USERDEFINED
:
3837 pTD
->vt
= VT_USERDEFINED
;
3838 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3844 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3847 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3849 pTD
->vt
= VT_CARRAY
;
3850 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3851 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3852 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3853 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3855 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3861 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3865 pTD
->vt
= VT_SAFEARRAY
;
3866 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3867 pTD
= pTD
->u
.lptdesc
;
3871 pTD
->vt
= *pType
& 0x3f;
3880 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3881 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3883 /* Handle [in/out] first */
3884 if((*pType
& 0xc000) == 0xc000)
3885 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3886 else if(*pType
& 0x8000)
3887 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3888 else if(*pType
& 0x4000)
3889 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3891 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3894 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3897 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3899 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3903 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3908 TLBRefType
*ref_type
;
3909 sltg_ref_lookup_t
*table
;
3910 HREFTYPE typelib_ref
;
3912 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3913 FIXME("Ref magic = %x\n", pRef
->magic
);
3916 name
= ( (char*)pRef
->names
+ pRef
->number
);
3918 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3919 table
->num
= pRef
->number
>> 3;
3921 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3923 /* We don't want the first href to be 0 */
3924 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3926 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3928 unsigned int lib_offs
, type_num
;
3930 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3932 name
+= SLTG_ReadStringA(name
, &refname
);
3933 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3934 FIXME_(typelib
)("Can't sscanf ref\n");
3935 if(lib_offs
!= 0xffff) {
3938 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3939 if(import
->offset
== lib_offs
)
3942 if(&import
->entry
== &pTL
->implib_list
) {
3943 char fname
[MAX_PATH
+1];
3947 import
= heap_alloc_zero(sizeof(*import
));
3948 import
->offset
= lib_offs
;
3949 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3950 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3951 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3952 &import
->wVersionMajor
,
3953 &import
->wVersionMinor
,
3954 &import
->lcid
, fname
) != 4) {
3955 FIXME_(typelib
)("can't sscanf ref %s\n",
3956 pNameTable
+ lib_offs
+ 40);
3958 len
= strlen(fname
);
3959 if(fname
[len
-1] != '#')
3960 FIXME("fname = %s\n", fname
);
3961 fname
[len
-1] = '\0';
3962 import
->name
= TLB_MultiByteToBSTR(fname
);
3963 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3965 ref_type
->pImpTLInfo
= import
;
3967 /* Store a reference to IDispatch */
3968 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3969 pTL
->dispatch_href
= typelib_ref
;
3971 } else { /* internal ref */
3972 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3974 ref_type
->reference
= typelib_ref
;
3975 ref_type
->index
= type_num
;
3978 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3980 table
->refs
[ref
] = typelib_ref
;
3983 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3984 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3985 dump_TLBRefType(pTL
);
3989 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3990 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3992 SLTG_ImplInfo
*info
;
3993 TLBImplType
*pImplType
;
3994 /* I don't really get this structure, usually it's 0x16 bytes
3995 long, but iuser.tlb contains some that are 0x18 bytes long.
3996 That's ok because we can use the next ptr to jump to the next
3997 one. But how do we know the length of the last one? The WORD
3998 at offs 0x8 might be the clue. For now I'm just assuming that
3999 the last one is the regular 0x16 bytes. */
4001 info
= (SLTG_ImplInfo
*)pBlk
;
4003 pTI
->typeattr
.cImplTypes
++;
4004 if(info
->next
== 0xffff)
4006 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4009 info
= (SLTG_ImplInfo
*)pBlk
;
4010 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
4011 pImplType
= pTI
->impltypes
;
4013 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4014 pImplType
->implflags
= info
->impltypeflags
;
4017 if(info
->next
== 0xffff)
4020 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4021 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4023 info
++; /* see comment at top of function */
4027 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4028 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4030 TLBVarDesc
*pVarDesc
;
4031 const TLBString
*prevName
= NULL
;
4032 SLTG_Variable
*pItem
;
4036 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4038 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4039 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4041 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4043 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4044 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4045 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4049 if (pItem
->name
== 0xfffe)
4050 pVarDesc
->Name
= prevName
;
4052 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4054 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4055 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4056 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4058 if(pItem
->flags
& 0x02)
4059 pType
= &pItem
->type
;
4061 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4063 if (pItem
->flags
& ~0xda)
4064 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4066 SLTG_DoElem(pType
, pBlk
,
4067 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4069 if (TRACE_ON(typelib
)) {
4071 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4072 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4075 if (pItem
->flags
& 0x40) {
4076 TRACE_(typelib
)("VAR_DISPATCH\n");
4077 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4079 else if (pItem
->flags
& 0x10) {
4080 TRACE_(typelib
)("VAR_CONST\n");
4081 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4082 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4083 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4084 if (pItem
->flags
& 0x08)
4085 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4087 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4093 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4095 TRACE_(typelib
)("len = %u\n", len
);
4096 if (len
== 0xffff) {
4099 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4100 str
= SysAllocStringLen(NULL
, alloc_len
);
4101 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4103 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4104 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4113 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4114 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4117 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4122 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4123 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4124 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4127 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4128 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4130 if (pItem
->flags
& 0x80)
4131 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4133 prevName
= pVarDesc
->Name
;
4135 pTI
->typeattr
.cVars
= cVars
;
4138 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4139 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4141 SLTG_Function
*pFunc
;
4143 TLBFuncDesc
*pFuncDesc
;
4145 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4147 pFuncDesc
= pTI
->funcdescs
;
4148 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4149 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4154 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4155 case SLTG_FUNCTION_MAGIC
:
4156 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4158 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4159 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4161 case SLTG_STATIC_FUNCTION_MAGIC
:
4162 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4165 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4168 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4170 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4171 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4172 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4173 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4174 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4175 pFuncDesc
->funcdesc
.oVft
= (pFunc
->vtblpos
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
4177 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4178 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4180 if(pFunc
->retnextopt
& 0x80)
4181 pType
= &pFunc
->rettype
;
4183 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4185 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4187 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4188 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4189 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4191 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4193 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4194 char *paramName
= pNameTable
+ *pArg
;
4196 /* If arg type follows then paramName points to the 2nd
4197 letter of the name, else the next WORD is an offset to
4198 the arg type and paramName points to the first letter.
4199 So let's take one char off paramName and see if we're
4200 pointing at an alpha-numeric char. However if *pArg is
4201 0xffff or 0xfffe then the param has no name, the former
4202 meaning that the next WORD is the type, the latter
4203 meaning that the next WORD is an offset to the type. */
4208 else if(*pArg
== 0xfffe) {
4212 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4217 if(HaveOffs
) { /* the next word is an offset to type */
4218 pType
= (WORD
*)(pBlk
+ *pArg
);
4219 SLTG_DoElem(pType
, pBlk
,
4220 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4225 pArg
= SLTG_DoElem(pArg
, pBlk
,
4226 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4229 /* Are we an optional param ? */
4230 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4231 pFuncDesc
->funcdesc
.cParamsOpt
)
4232 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4235 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4236 paramName
- pNameTable
, pTI
->pTypeLib
);
4238 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4242 pTI
->typeattr
.cFuncs
= cFuncs
;
4245 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4246 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4247 SLTG_TypeInfoTail
*pTITail
)
4250 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4252 if(pTIHeader
->href_table
!= 0xffffffff) {
4253 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4259 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4260 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4262 heap_free(ref_lookup
);
4266 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4267 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4268 const SLTG_TypeInfoTail
*pTITail
)
4271 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4273 if(pTIHeader
->href_table
!= 0xffffffff) {
4274 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4280 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4281 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4284 if (pTITail
->funcs_off
!= 0xffff)
4285 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4287 heap_free(ref_lookup
);
4289 if (TRACE_ON(typelib
))
4290 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4293 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4294 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4295 const SLTG_TypeInfoTail
*pTITail
)
4297 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4300 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4301 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4302 const SLTG_TypeInfoTail
*pTITail
)
4305 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4307 if (pTITail
->simple_alias
) {
4308 /* if simple alias, no more processing required */
4309 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4310 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4314 if(pTIHeader
->href_table
!= 0xffffffff) {
4315 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4319 /* otherwise it is an offset to a type */
4320 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4322 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4323 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4325 heap_free(ref_lookup
);
4328 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4329 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4330 const SLTG_TypeInfoTail
*pTITail
)
4332 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4333 if (pTIHeader
->href_table
!= 0xffffffff)
4334 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4337 if (pTITail
->vars_off
!= 0xffff)
4338 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4340 if (pTITail
->funcs_off
!= 0xffff)
4341 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4343 if (pTITail
->impls_off
!= 0xffff)
4344 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4346 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4347 * of dispinterface functions including the IDispatch ones, so
4348 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4349 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4351 heap_free(ref_lookup
);
4352 if (TRACE_ON(typelib
))
4353 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4356 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4357 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4358 const SLTG_TypeInfoTail
*pTITail
)
4360 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4363 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4364 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4365 const SLTG_TypeInfoTail
*pTITail
)
4367 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4368 if (pTIHeader
->href_table
!= 0xffffffff)
4369 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4372 if (pTITail
->vars_off
!= 0xffff)
4373 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4375 if (pTITail
->funcs_off
!= 0xffff)
4376 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4377 heap_free(ref_lookup
);
4378 if (TRACE_ON(typelib
))
4382 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4383 manageable copy of it into this */
4396 } SLTG_InternalOtherTypeInfo
;
4398 /****************************************************************************
4399 * ITypeLib2_Constructor_SLTG
4401 * loading a SLTG typelib from an in-memory image
4403 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4405 ITypeLibImpl
*pTypeLibImpl
;
4406 SLTG_Header
*pHeader
;
4407 SLTG_BlkEntry
*pBlkEntry
;
4411 LPVOID pBlk
, pFirstBlk
;
4412 SLTG_LibBlk
*pLibBlk
;
4413 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4414 char *pAfterOTIBlks
= NULL
;
4415 char *pNameTable
, *ptr
;
4418 ITypeInfoImpl
**ppTypeInfoImpl
;
4420 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4423 pTypeLibImpl
= TypeLibImpl_Constructor();
4424 if (!pTypeLibImpl
) return NULL
;
4428 TRACE_(typelib
)("header:\n");
4429 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4430 pHeader
->nrOfFileBlks
);
4431 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4432 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4433 pHeader
->SLTG_magic
);
4437 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4438 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4440 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4441 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4443 /* Next we have a magic block */
4444 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4446 /* Let's see if we're still in sync */
4447 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4448 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4449 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4452 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4453 sizeof(SLTG_DIR_MAGIC
))) {
4454 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4458 pIndex
= (SLTG_Index
*)(pMagic
+1);
4460 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4462 pFirstBlk
= pPad9
+ 1;
4464 /* We'll set up a ptr to the main library block, which is the last one. */
4466 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4467 pBlkEntry
[order
].next
!= 0;
4468 order
= pBlkEntry
[order
].next
- 1) {
4469 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4473 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4475 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4480 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4482 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4485 ptr
= (char*)pLibBlk
+ len
;
4487 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4491 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4493 w
= *(WORD
*)(ptr
+ 2);
4496 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4497 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4498 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4500 w
= *(WORD
*)(ptr
+ 4 + len
);
4502 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4504 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4505 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4506 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4508 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4509 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4510 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4512 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4513 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4516 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4517 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4518 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4519 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4520 len
+= sizeof(SLTG_OtherTypeInfo
);
4524 pAfterOTIBlks
= ptr
;
4526 /* Skip this WORD and get the next DWORD */
4527 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4529 /* Now add this to pLibBLk look at what we're pointing at and
4530 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4531 dust and we should be pointing at the beginning of the name
4534 pNameTable
= (char*)pLibBlk
+ len
;
4536 switch(*(WORD
*)pNameTable
) {
4543 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4547 pNameTable
+= 0x216;
4551 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4553 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4556 /* Hopefully we now have enough ptrs set up to actually read in
4557 some TypeInfos. It's not clear which order to do them in, so
4558 I'll just follow the links along the BlkEntry chain and read
4559 them in the order in which they are in the file */
4561 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4562 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4564 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4565 pBlkEntry
[order
].next
!= 0;
4566 order
= pBlkEntry
[order
].next
- 1, i
++) {
4568 SLTG_TypeInfoHeader
*pTIHeader
;
4569 SLTG_TypeInfoTail
*pTITail
;
4570 SLTG_MemberHeader
*pMemHeader
;
4572 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4573 FIXME_(typelib
)("Index strings don't match\n");
4574 heap_free(pOtherTypeInfoBlks
);
4579 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4580 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4581 heap_free(pOtherTypeInfoBlks
);
4584 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4585 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4586 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4588 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4589 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4590 (*ppTypeInfoImpl
)->index
= i
;
4591 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4592 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4593 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4594 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4595 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4596 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4597 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4598 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4600 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4601 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4603 if((pTIHeader
->typeflags1
& 7) != 2)
4604 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4605 if(pTIHeader
->typeflags3
!= 2)
4606 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4608 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4609 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4610 typekind_desc
[pTIHeader
->typekind
],
4611 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4612 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4614 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4616 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4618 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4619 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4620 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4622 switch(pTIHeader
->typekind
) {
4624 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4625 pTIHeader
, pTITail
);
4629 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4630 pTIHeader
, pTITail
);
4633 case TKIND_INTERFACE
:
4634 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4635 pTIHeader
, pTITail
);
4639 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4640 pTIHeader
, pTITail
);
4644 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4645 pTIHeader
, pTITail
);
4648 case TKIND_DISPATCH
:
4649 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4650 pTIHeader
, pTITail
);
4654 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4655 pTIHeader
, pTITail
);
4659 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4664 /* could get cFuncs, cVars and cImplTypes from here
4665 but we've already set those */
4666 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4682 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4685 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4686 FIXME("Somehow processed %d TypeInfos\n", i
);
4687 heap_free(pOtherTypeInfoBlks
);
4691 heap_free(pOtherTypeInfoBlks
);
4692 return &pTypeLibImpl
->ITypeLib2_iface
;
4695 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4697 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4699 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4701 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4702 IsEqualIID(riid
,&IID_ITypeLib
)||
4703 IsEqualIID(riid
,&IID_ITypeLib2
))
4705 *ppv
= &This
->ITypeLib2_iface
;
4707 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4708 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4710 *ppv
= &This
->ICreateTypeLib2_iface
;
4715 TRACE("-- Interface: E_NOINTERFACE\n");
4716 return E_NOINTERFACE
;
4719 IUnknown_AddRef((IUnknown
*)*ppv
);
4723 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4725 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4726 ULONG ref
= InterlockedIncrement(&This
->ref
);
4728 TRACE("(%p) ref=%u\n", This
, ref
);
4733 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4735 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4736 ULONG ref
= InterlockedDecrement(&This
->ref
);
4738 TRACE("(%p) ref=%u\n",This
, ref
);
4742 TLBImpLib
*pImpLib
, *pImpLibNext
;
4743 TLBRefType
*ref_type
, *ref_type_next
;
4744 TLBString
*tlbstr
, *tlbstr_next
;
4745 TLBGuid
*tlbguid
, *tlbguid_next
;
4748 /* remove cache entry */
4751 TRACE("removing from cache list\n");
4752 EnterCriticalSection(&cache_section
);
4753 if(This
->entry
.next
)
4754 list_remove(&This
->entry
);
4755 LeaveCriticalSection(&cache_section
);
4756 heap_free(This
->path
);
4758 TRACE(" destroying ITypeLib(%p)\n",This
);
4760 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4761 list_remove(&tlbstr
->entry
);
4762 SysFreeString(tlbstr
->str
);
4766 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4767 list_remove(&tlbstr
->entry
);
4768 SysFreeString(tlbstr
->str
);
4772 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4773 list_remove(&tlbguid
->entry
);
4777 TLB_FreeCustData(&This
->custdata_list
);
4779 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4780 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4781 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4783 heap_free(This
->pTypeDesc
);
4785 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4787 if (pImpLib
->pImpTypeLib
)
4788 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4789 SysFreeString(pImpLib
->name
);
4791 list_remove(&pImpLib
->entry
);
4795 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, ref_type_next
, &This
->ref_list
, TLBRefType
, entry
)
4797 list_remove(&ref_type
->entry
);
4798 heap_free(ref_type
);
4801 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4802 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4803 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4805 heap_free(This
->typeinfos
);
4813 /* ITypeLib::GetTypeInfoCount
4815 * Returns the number of type descriptions in the type library
4817 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4819 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4820 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4821 return This
->TypeInfoCount
;
4824 /* ITypeLib::GetTypeInfo
4826 * retrieves the specified type description in the library.
4828 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4831 ITypeInfo
**ppTInfo
)
4833 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4835 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4838 return E_INVALIDARG
;
4840 if(index
>= This
->TypeInfoCount
)
4841 return TYPE_E_ELEMENTNOTFOUND
;
4843 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4844 ITypeInfo_AddRef(*ppTInfo
);
4850 /* ITypeLibs::GetTypeInfoType
4852 * Retrieves the type of a type description.
4854 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4859 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4861 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4864 return E_INVALIDARG
;
4866 if(index
>= This
->TypeInfoCount
)
4867 return TYPE_E_ELEMENTNOTFOUND
;
4869 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4874 /* ITypeLib::GetTypeInfoOfGuid
4876 * Retrieves the type description that corresponds to the specified GUID.
4879 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4882 ITypeInfo
**ppTInfo
)
4884 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4887 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4889 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4890 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4891 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4892 ITypeInfo_AddRef(*ppTInfo
);
4897 return TYPE_E_ELEMENTNOTFOUND
;
4900 /* ITypeLib::GetLibAttr
4902 * Retrieves the structure that contains the library's attributes.
4905 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4909 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4911 TRACE("(%p, %p)\n", This
, attr
);
4913 if (!attr
) return E_INVALIDARG
;
4915 *attr
= heap_alloc(sizeof(**attr
));
4916 if (!*attr
) return E_OUTOFMEMORY
;
4918 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4919 (*attr
)->lcid
= This
->set_lcid
;
4920 (*attr
)->syskind
= This
->syskind
;
4921 (*attr
)->wMajorVerNum
= This
->ver_major
;
4922 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4923 (*attr
)->wLibFlags
= This
->libflags
;
4928 /* ITypeLib::GetTypeComp
4930 * Enables a client compiler to bind to a library's types, variables,
4931 * constants, and global functions.
4934 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4936 ITypeComp
**ppTComp
)
4938 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4940 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4941 *ppTComp
= &This
->ITypeComp_iface
;
4942 ITypeComp_AddRef(*ppTComp
);
4947 /* ITypeLib::GetDocumentation
4949 * Retrieves the library's documentation string, the complete Help file name
4950 * and path, and the context identifier for the library Help topic in the Help
4953 * On a successful return all non-null BSTR pointers will have been set,
4956 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4960 BSTR
*pBstrDocString
,
4961 DWORD
*pdwHelpContext
,
4962 BSTR
*pBstrHelpFile
)
4964 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4965 HRESULT result
= E_INVALIDARG
;
4968 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4970 pBstrName
, pBstrDocString
,
4971 pdwHelpContext
, pBstrHelpFile
);
4975 /* documentation for the typelib */
4980 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4988 if (This
->DocString
)
4990 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4994 *pBstrDocString
= NULL
;
4998 *pdwHelpContext
= This
->dwHelpContext
;
5004 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5008 *pBstrHelpFile
= NULL
;
5015 /* for a typeinfo */
5016 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5018 if(SUCCEEDED(result
))
5020 result
= ITypeInfo_GetDocumentation(pTInfo
,
5024 pdwHelpContext
, pBstrHelpFile
);
5026 ITypeInfo_Release(pTInfo
);
5031 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5033 if (pBstrName
) SysFreeString (*pBstrName
);
5035 return STG_E_INSUFFICIENTMEMORY
;
5040 * Indicates whether a passed-in string contains the name of a type or member
5041 * described in the library.
5044 static HRESULT WINAPI
ITypeLib2_fnIsName(
5050 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5052 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5054 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5058 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5059 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5060 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5061 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5062 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5064 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5065 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5066 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5067 goto ITypeLib2_fnIsName_exit
;
5070 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5071 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5072 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5078 ITypeLib2_fnIsName_exit
:
5079 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5080 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5085 /* ITypeLib::FindName
5087 * Finds occurrences of a type description in a type library. This may be used
5088 * to quickly verify that a name exists in a type library.
5091 static HRESULT WINAPI
ITypeLib2_fnFindName(
5095 ITypeInfo
**ppTInfo
,
5099 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5104 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5106 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5107 return E_INVALIDARG
;
5109 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5110 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5111 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5115 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5116 memid
[count
] = MEMBERID_NIL
;
5117 goto ITypeLib2_fnFindName_exit
;
5120 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5121 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5123 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5124 memid
[count
] = func
->funcdesc
.memid
;
5125 goto ITypeLib2_fnFindName_exit
;
5129 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->typeattr
.cVars
, name
);
5131 memid
[count
] = var
->vardesc
.memid
;
5132 goto ITypeLib2_fnFindName_exit
;
5136 ITypeLib2_fnFindName_exit
:
5137 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5138 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5141 TRACE("found %d typeinfos\n", count
);
5148 /* ITypeLib::ReleaseTLibAttr
5150 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5153 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5155 TLIBATTR
*pTLibAttr
)
5157 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5158 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5159 heap_free(pTLibAttr
);
5162 /* ITypeLib2::GetCustData
5164 * gets the custom data
5166 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5171 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5172 TLBCustData
*pCData
;
5174 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5176 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5178 return TYPE_E_ELEMENTNOTFOUND
;
5180 VariantInit(pVarVal
);
5181 VariantCopy(pVarVal
, &pCData
->data
);
5186 /* ITypeLib2::GetLibStatistics
5188 * Returns statistics about a type library that are required for efficient
5189 * sizing of hash tables.
5192 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5194 ULONG
*pcUniqueNames
,
5195 ULONG
*pcchUniqueNames
)
5197 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5199 FIXME("(%p): stub!\n", This
);
5201 if(pcUniqueNames
) *pcUniqueNames
=1;
5202 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5206 /* ITypeLib2::GetDocumentation2
5208 * Retrieves the library's documentation string, the complete Help file name
5209 * and path, the localization context to use, and the context ID for the
5210 * library Help topic in the Help file.
5213 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5217 BSTR
*pbstrHelpString
,
5218 DWORD
*pdwHelpStringContext
,
5219 BSTR
*pbstrHelpStringDll
)
5221 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5225 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5227 /* the help string should be obtained from the helpstringdll,
5228 * using the _DLLGetDocumentation function, based on the supplied
5229 * lcid. Nice to do sometime...
5233 /* documentation for the typelib */
5235 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5236 if(pdwHelpStringContext
)
5237 *pdwHelpStringContext
=This
->dwHelpContext
;
5238 if(pbstrHelpStringDll
)
5239 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5245 /* for a typeinfo */
5246 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5248 if(SUCCEEDED(result
))
5250 ITypeInfo2
* pTInfo2
;
5251 result
= ITypeInfo_QueryInterface(pTInfo
,
5253 (LPVOID
*) &pTInfo2
);
5255 if(SUCCEEDED(result
))
5257 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5261 pdwHelpStringContext
,
5262 pbstrHelpStringDll
);
5264 ITypeInfo2_Release(pTInfo2
);
5267 ITypeInfo_Release(pTInfo
);
5273 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5275 TLBCustData
*pCData
;
5279 ct
= list_count(custdata_list
);
5281 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5282 if(!pCustData
->prgCustData
)
5283 return E_OUTOFMEMORY
;
5285 pCustData
->cCustData
= ct
;
5287 cdi
= pCustData
->prgCustData
;
5288 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5289 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5290 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5298 /* ITypeLib2::GetAllCustData
5300 * Gets all custom data items for the library.
5303 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5305 CUSTDATA
*pCustData
)
5307 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5308 TRACE("(%p)->(%p)\n", This
, pCustData
);
5309 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5312 static const ITypeLib2Vtbl tlbvt
= {
5313 ITypeLib2_fnQueryInterface
,
5315 ITypeLib2_fnRelease
,
5316 ITypeLib2_fnGetTypeInfoCount
,
5317 ITypeLib2_fnGetTypeInfo
,
5318 ITypeLib2_fnGetTypeInfoType
,
5319 ITypeLib2_fnGetTypeInfoOfGuid
,
5320 ITypeLib2_fnGetLibAttr
,
5321 ITypeLib2_fnGetTypeComp
,
5322 ITypeLib2_fnGetDocumentation
,
5324 ITypeLib2_fnFindName
,
5325 ITypeLib2_fnReleaseTLibAttr
,
5327 ITypeLib2_fnGetCustData
,
5328 ITypeLib2_fnGetLibStatistics
,
5329 ITypeLib2_fnGetDocumentation2
,
5330 ITypeLib2_fnGetAllCustData
5334 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5336 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5338 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5341 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5343 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5345 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5348 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5350 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5352 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5355 static HRESULT WINAPI
ITypeLibComp_fnBind(
5360 ITypeInfo
** ppTInfo
,
5361 DESCKIND
* pDescKind
,
5364 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5365 BOOL typemismatch
= FALSE
;
5368 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5370 *pDescKind
= DESCKIND_NONE
;
5371 pBindPtr
->lptcomp
= NULL
;
5374 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5375 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5376 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5378 /* FIXME: check wFlags here? */
5379 /* FIXME: we should use a hash table to look this info up using lHash
5380 * instead of an O(n) search */
5381 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5382 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5384 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5386 *pDescKind
= DESCKIND_TYPECOMP
;
5387 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5388 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5389 TRACE("module or enum: %s\n", debugstr_w(szName
));
5394 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5395 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5397 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5400 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5401 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5403 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5406 else if (hr
== TYPE_E_TYPEMISMATCH
)
5407 typemismatch
= TRUE
;
5410 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5411 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5413 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5415 ITypeInfo
*subtypeinfo
;
5417 DESCKIND subdesckind
;
5419 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5420 &subtypeinfo
, &subdesckind
, &subbindptr
);
5421 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5423 TYPEDESC tdesc_appobject
;
5424 const VARDESC vardesc_appobject
=
5427 NULL
, /* lpstrSchema */
5442 VAR_STATIC
/* varkind */
5445 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5446 tdesc_appobject
.vt
= VT_USERDEFINED
;
5448 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5450 /* cleanup things filled in by Bind call so we can put our
5451 * application object data in there instead */
5452 switch (subdesckind
)
5454 case DESCKIND_FUNCDESC
:
5455 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5457 case DESCKIND_VARDESC
:
5458 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5463 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5465 if (pTypeInfo
->hreftype
== -1)
5466 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5468 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5472 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5473 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5474 ITypeInfo_AddRef(*ppTInfo
);
5477 else if (hr
== TYPE_E_TYPEMISMATCH
)
5478 typemismatch
= TRUE
;
5484 TRACE("type mismatch %s\n", debugstr_w(szName
));
5485 return TYPE_E_TYPEMISMATCH
;
5489 TRACE("name not found %s\n", debugstr_w(szName
));
5494 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5498 ITypeInfo
** ppTInfo
,
5499 ITypeComp
** ppTComp
)
5501 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5502 ITypeInfoImpl
*info
;
5504 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5506 if(!szName
|| !ppTInfo
|| !ppTComp
)
5507 return E_INVALIDARG
;
5509 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5516 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5517 ITypeInfo_AddRef(*ppTInfo
);
5518 *ppTComp
= &info
->ITypeComp_iface
;
5519 ITypeComp_AddRef(*ppTComp
);
5524 static const ITypeCompVtbl tlbtcvt
=
5527 ITypeLibComp_fnQueryInterface
,
5528 ITypeLibComp_fnAddRef
,
5529 ITypeLibComp_fnRelease
,
5531 ITypeLibComp_fnBind
,
5532 ITypeLibComp_fnBindType
5535 /*================== ITypeInfo(2) Methods ===================================*/
5536 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5538 ITypeInfoImpl
*pTypeInfoImpl
;
5540 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5543 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5544 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5545 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5546 pTypeInfoImpl
->ref
= 0;
5547 pTypeInfoImpl
->hreftype
= -1;
5548 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5549 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5550 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5551 list_init(pTypeInfoImpl
->pcustdata_list
);
5553 TRACE("(%p)\n", pTypeInfoImpl
);
5554 return pTypeInfoImpl
;
5557 /* ITypeInfo::QueryInterface
5559 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5564 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5566 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5569 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5570 IsEqualIID(riid
,&IID_ITypeInfo
)||
5571 IsEqualIID(riid
,&IID_ITypeInfo2
))
5572 *ppvObject
= &This
->ITypeInfo2_iface
;
5573 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5574 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5575 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5576 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5577 *ppvObject
= &This
->ITypeComp_iface
;
5580 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5581 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5584 TRACE("-- Interface: E_NOINTERFACE\n");
5585 return E_NOINTERFACE
;
5588 /* ITypeInfo::AddRef
5590 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5592 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5593 ULONG ref
= InterlockedIncrement(&This
->ref
);
5595 TRACE("(%p)->ref is %u\n",This
, ref
);
5597 if (ref
== 1 /* incremented from 0 */)
5598 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5603 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5607 TRACE("destroying ITypeInfo(%p)\n",This
);
5609 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5612 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5613 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5615 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5616 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5617 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5618 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5620 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5621 heap_free(pFInfo
->pParamDesc
);
5622 TLB_FreeCustData(&pFInfo
->custdata_list
);
5624 heap_free(This
->funcdescs
);
5626 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5628 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5629 if (pVInfo
->vardesc_create
) {
5630 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5631 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5632 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5633 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5635 TLB_FreeCustData(&pVInfo
->custdata_list
);
5637 heap_free(This
->vardescs
);
5639 if(This
->impltypes
){
5640 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5641 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5642 TLB_FreeCustData(&pImpl
->custdata_list
);
5644 heap_free(This
->impltypes
);
5647 TLB_FreeCustData(&This
->custdata_list
);
5652 /* ITypeInfo::Release
5654 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5656 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5657 ULONG ref
= InterlockedDecrement(&This
->ref
);
5659 TRACE("(%p)->(%u)\n",This
, ref
);
5663 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5664 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5665 if (not_attached_to_typelib
)
5667 /* otherwise This will be freed when typelib is freed */
5673 /* ITypeInfo::GetTypeAttr
5675 * Retrieves a TYPEATTR structure that contains the attributes of the type
5679 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5680 LPTYPEATTR
*ppTypeAttr
)
5682 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5685 TRACE("(%p)\n",This
);
5687 size
= sizeof(**ppTypeAttr
);
5688 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5689 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5691 *ppTypeAttr
= heap_alloc(size
);
5693 return E_OUTOFMEMORY
;
5695 **ppTypeAttr
= This
->typeattr
;
5696 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5698 if (This
->tdescAlias
)
5699 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5701 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5702 /* This should include all the inherited funcs */
5703 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5704 /* This is always the size of IDispatch's vtbl */
5705 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5706 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5711 /* ITypeInfo::GetTypeComp
5713 * Retrieves the ITypeComp interface for the type description, which enables a
5714 * client compiler to bind to the type description's members.
5717 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5718 ITypeComp
* *ppTComp
)
5720 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5722 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5724 *ppTComp
= &This
->ITypeComp_iface
;
5725 ITypeComp_AddRef(*ppTComp
);
5729 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5731 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5732 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5733 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5737 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5740 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5741 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5743 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5744 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5745 *buffer
+= sizeof(PARAMDESCEX
);
5746 *pparamdescex_dest
= *pparamdescex_src
;
5747 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5748 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5749 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5750 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5753 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5757 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5759 UINT len
= SysStringLen(str
), i
;
5760 for (i
= 0; i
< len
; ++i
)
5766 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5768 if (V_VT(var
) == VT_INT
)
5769 return VariantChangeType(var
, var
, 0, VT_I4
);
5770 else if (V_VT(var
) == VT_UINT
)
5771 return VariantChangeType(var
, var
, 0, VT_UI4
);
5772 else if (V_VT(var
) == VT_BSTR
)
5773 return TLB_SanitizeBSTR(V_BSTR(var
));
5778 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5780 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5781 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5784 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5788 SIZE_T size
= sizeof(*src
);
5792 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5793 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5794 for (i
= 0; i
< src
->cParams
; i
++)
5796 size
+= sizeof(ELEMDESC
);
5797 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5800 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5801 if (!dest
) return E_OUTOFMEMORY
;
5804 if (dispinterface
) /* overwrite funckind */
5805 dest
->funckind
= FUNC_DISPATCH
;
5806 buffer
= (char *)(dest
+ 1);
5808 dest
->oVft
= dest
->oVft
& 0xFFFC;
5810 if (dest
->cScodes
) {
5811 dest
->lprgscode
= (SCODE
*)buffer
;
5812 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5813 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5815 dest
->lprgscode
= NULL
;
5817 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5820 SysFreeString((BSTR
)dest
);
5824 if (dest
->cParams
) {
5825 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5826 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5827 for (i
= 0; i
< src
->cParams
; i
++)
5829 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5835 /* undo the above actions */
5836 for (i
= i
- 1; i
>= 0; i
--)
5837 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5838 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5839 SysFreeString((BSTR
)dest
);
5843 dest
->lprgelemdescParam
= NULL
;
5845 /* special treatment for dispinterfaces: this makes functions appear
5846 * to return their [retval] value when it is really returning an
5848 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5850 if (dest
->cParams
&&
5851 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5853 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5854 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5856 ERR("elemdesc should have started with VT_PTR instead of:\n");
5858 dump_ELEMDESC(elemdesc
);
5859 return E_UNEXPECTED
;
5862 /* copy last parameter to the return value. we are using a flat
5863 * buffer so there is no danger of leaking memory in
5865 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5867 /* remove the last parameter */
5871 /* otherwise this function is made to appear to have no return
5873 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5881 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5883 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5884 if (var_desc
->varkind
== VAR_CONST
)
5885 VariantClear(var_desc
->u
.lpvarValue
);
5886 SysFreeString((BSTR
)var_desc
);
5889 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5891 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5893 if (index
>= This
->typeattr
.cFuncs
)
5894 return TYPE_E_ELEMENTNOTFOUND
;
5896 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5900 /* internal function to make the inherited interfaces' methods appear
5901 * part of the interface */
5902 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5903 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5905 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5907 UINT implemented_funcs
= 0;
5912 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5916 ITypeInfo
*pSubTypeInfo
;
5919 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5923 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5926 &sub_funcs
, hrefoffset
);
5927 implemented_funcs
+= sub_funcs
;
5928 ITypeInfo_Release(pSubTypeInfo
);
5931 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5935 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5939 if (index
< implemented_funcs
)
5940 return E_INVALIDARG
;
5941 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5945 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5947 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5950 switch (pTypeDesc
->vt
)
5952 case VT_USERDEFINED
:
5953 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5957 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5960 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5968 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5971 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5972 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5973 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5976 /* ITypeInfo::GetFuncDesc
5978 * Retrieves the FUNCDESC structure that contains information about a
5979 * specified function.
5982 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5983 LPFUNCDESC
*ppFuncDesc
)
5985 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5986 const FUNCDESC
*internal_funcdesc
;
5988 UINT hrefoffset
= 0;
5990 TRACE("(%p) index %d\n", This
, index
);
5993 return E_INVALIDARG
;
5995 if (This
->needs_layout
)
5996 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5998 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5999 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
6000 &internal_funcdesc
, NULL
,
6003 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6004 &internal_funcdesc
);
6007 WARN("description for function %d not found\n", index
);
6011 hr
= TLB_AllocAndInitFuncDesc(
6014 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6016 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
6017 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6019 TRACE("-- 0x%08x\n", hr
);
6023 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6027 SIZE_T size
= sizeof(*src
);
6030 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6031 if (src
->varkind
== VAR_CONST
)
6032 size
+= sizeof(VARIANT
);
6033 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6035 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6036 if (!dest
) return E_OUTOFMEMORY
;
6039 buffer
= (char *)(dest
+ 1);
6040 if (src
->lpstrSchema
)
6043 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6044 len
= strlenW(src
->lpstrSchema
);
6045 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6046 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6049 if (src
->varkind
== VAR_CONST
)
6053 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6054 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6055 buffer
+= sizeof(VARIANT
);
6056 VariantInit(dest
->u
.lpvarValue
);
6057 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6060 SysFreeString((BSTR
)dest
);
6064 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6067 if (src
->varkind
== VAR_CONST
)
6068 VariantClear(dest
->u
.lpvarValue
);
6069 SysFreeString((BSTR
)dest
);
6076 /* ITypeInfo::GetVarDesc
6078 * Retrieves a VARDESC structure that describes the specified variable.
6081 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6082 LPVARDESC
*ppVarDesc
)
6084 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6085 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6087 TRACE("(%p) index %d\n", This
, index
);
6089 if(index
>= This
->typeattr
.cVars
)
6090 return TYPE_E_ELEMENTNOTFOUND
;
6092 if (This
->needs_layout
)
6093 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6095 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6098 /* ITypeInfo_GetNames
6100 * Retrieves the variable with the specified member ID (or the name of the
6101 * property or method and its parameters) that correspond to the specified
6104 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6105 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6107 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6108 const TLBFuncDesc
*pFDesc
;
6109 const TLBVarDesc
*pVDesc
;
6111 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6114 return E_INVALIDARG
;
6118 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
6121 if(!cMaxNames
|| !pFDesc
->Name
)
6124 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6127 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6128 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6130 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6136 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
6139 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6144 if(This
->impltypes
&&
6145 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
6146 /* recursive search */
6149 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6150 if(SUCCEEDED(result
))
6152 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6153 ITypeInfo_Release(pTInfo
);
6156 WARN("Could not search inherited interface!\n");
6160 WARN("no names found\n");
6163 return TYPE_E_ELEMENTNOTFOUND
;
6169 /* ITypeInfo::GetRefTypeOfImplType
6171 * If a type description describes a COM class, it retrieves the type
6172 * description of the implemented interface types. For an interface,
6173 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6177 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6182 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6185 TRACE("(%p) index %d\n", This
, index
);
6186 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6190 /* only valid on dual interfaces;
6191 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6194 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6200 hr
= TYPE_E_ELEMENTNOTFOUND
;
6203 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6205 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6206 *pRefType
= This
->pTypeLib
->dispatch_href
;
6210 if(index
>= This
->typeattr
.cImplTypes
)
6211 hr
= TYPE_E_ELEMENTNOTFOUND
;
6213 *pRefType
= This
->impltypes
[index
].hRef
;
6214 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6222 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6224 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6230 /* ITypeInfo::GetImplTypeFlags
6232 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6233 * or base interface in a type description.
6235 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6236 UINT index
, INT
*pImplTypeFlags
)
6238 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6240 TRACE("(%p) index %d\n", This
, index
);
6243 return E_INVALIDARG
;
6245 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6246 *pImplTypeFlags
= 0;
6250 if(index
>= This
->typeattr
.cImplTypes
)
6251 return TYPE_E_ELEMENTNOTFOUND
;
6253 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6259 * Maps between member names and member IDs, and parameter names and
6262 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6263 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6265 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6266 const TLBVarDesc
*pVDesc
;
6270 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6273 /* init out parameters in case of failure */
6274 for (i
= 0; i
< cNames
; i
++)
6275 pMemId
[i
] = MEMBERID_NIL
;
6277 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6279 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6280 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6281 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6282 for(i
=1; i
< cNames
; i
++){
6283 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6284 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6286 if( j
<pFDesc
->funcdesc
.cParams
)
6289 ret
=DISP_E_UNKNOWNNAME
;
6291 TRACE("-- 0x%08x\n", ret
);
6295 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, *rgszNames
);
6298 *pMemId
= pVDesc
->vardesc
.memid
;
6301 /* not found, see if it can be found in an inherited interface */
6302 if(This
->impltypes
) {
6303 /* recursive search */
6305 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6307 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6308 ITypeInfo_Release(pTInfo
);
6311 WARN("Could not search inherited interface!\n");
6313 WARN("no names found\n");
6314 return DISP_E_UNKNOWNNAME
;
6320 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6321 extern double call_double_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6322 __ASM_GLOBAL_FUNC( call_method
,
6324 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6325 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6326 "movl %esp,%ebp\n\t"
6327 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6329 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6331 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6332 "movl 12(%ebp),%edx\n\t"
6333 "movl %esp,%edi\n\t"
6336 "subl %edx,%edi\n\t"
6337 "andl $~15,%edi\n\t"
6338 "movl %edi,%esp\n\t"
6339 "movl 12(%ebp),%ecx\n\t"
6340 "movl 16(%ebp),%esi\n\t"
6343 "1:\tcall *8(%ebp)\n\t"
6344 "subl %esp,%edi\n\t"
6345 "movl 20(%ebp),%ecx\n\t"
6346 "movl %edi,(%ecx)\n\t"
6347 "leal -8(%ebp),%esp\n\t"
6349 __ASM_CFI(".cfi_same_value %edi\n\t")
6351 __ASM_CFI(".cfi_same_value %esi\n\t")
6353 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6354 __ASM_CFI(".cfi_same_value %ebp\n\t")
6356 __ASM_GLOBAL_FUNC( call_double_method
,
6357 "jmp " __ASM_NAME("call_method") )
6359 #elif defined(__x86_64__)
6361 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6362 extern double CDECL
call_double_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6363 __ASM_GLOBAL_FUNC( call_method
,
6365 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6366 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6367 "movq %rsp,%rbp\n\t"
6368 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6370 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6372 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6373 "movq %rcx,%rax\n\t"
6376 "cmovgq %rdx,%rcx\n\t"
6377 "leaq 0(,%rcx,8),%rdx\n\t"
6378 "subq %rdx,%rsp\n\t"
6379 "andq $~15,%rsp\n\t"
6380 "movq %rsp,%rdi\n\t"
6383 "movq 0(%rsp),%rcx\n\t"
6384 "movq 8(%rsp),%rdx\n\t"
6385 "movq 16(%rsp),%r8\n\t"
6386 "movq 24(%rsp),%r9\n\t"
6387 "movq 0(%rsp),%xmm0\n\t"
6388 "movq 8(%rsp),%xmm1\n\t"
6389 "movq 16(%rsp),%xmm2\n\t"
6390 "movq 24(%rsp),%xmm3\n\t"
6392 "leaq -16(%rbp),%rsp\n\t"
6394 __ASM_CFI(".cfi_same_value %rdi\n\t")
6396 __ASM_CFI(".cfi_same_value %rsi\n\t")
6397 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6399 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6400 __ASM_CFI(".cfi_same_value %rbp\n\t")
6402 __ASM_GLOBAL_FUNC( call_double_method
,
6403 "jmp " __ASM_NAME("call_method") )
6405 #elif defined(__arm__)
6407 extern LONGLONG CDECL
call_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6408 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6409 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6410 __ASM_GLOBAL_FUNC( call_method
,
6413 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6414 * 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)
6417 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6418 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6420 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6421 "beq 1f\n\t" /* Skip allocation if no stack args */
6422 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6423 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6424 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6425 "subs r1, r1, #4\n\t" /* Decrement count */
6426 "bgt 2b\n\t" /* Loop till done */
6430 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6432 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6433 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6435 "blx ip\n\t" /* Call the target function */
6437 "mov sp, fp\n\t" /* Clean the stack using fp */
6438 "pop {fp, pc}\n\t" /* Restore fp and return */
6440 __ASM_GLOBAL_FUNC( call_float_method
,
6441 "b " __ASM_NAME("call_method") )
6442 __ASM_GLOBAL_FUNC( call_double_method
,
6443 "b " __ASM_NAME("call_method") )
6445 #endif /* __arm__ */
6447 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6450 ITypeInfo
*tinfo2
= NULL
;
6451 TYPEATTR
*tattr
= NULL
;
6453 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6456 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6458 tdesc
->u
.hreftype
, hr
);
6461 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6464 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6465 ITypeInfo_Release(tinfo2
);
6469 switch (tattr
->typekind
)
6476 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6479 case TKIND_INTERFACE
:
6480 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6486 case TKIND_DISPATCH
:
6495 FIXME("TKIND_RECORD unhandled.\n");
6500 FIXME("TKIND_UNION unhandled.\n");
6505 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6509 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6510 ITypeInfo_Release(tinfo2
);
6514 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6518 /* enforce only one level of pointer indirection */
6519 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6521 tdesc
= tdesc
->u
.lptdesc
;
6523 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6524 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6525 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6526 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6527 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6529 VARTYPE vt_userdefined
= 0;
6530 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6531 if (tdesc
->vt
== VT_PTR
)
6533 vt_userdefined
= VT_BYREF
;
6534 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6536 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6538 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6539 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6541 *vt
|= vt_userdefined
;
6553 case VT_USERDEFINED
:
6554 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6561 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6562 hr
= DISP_E_BADVARTYPE
;
6566 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6581 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, HREFTYPE href
, GUID
*guid
)
6588 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
6592 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6594 ITypeInfo_Release(tinfo2
);
6598 switch(tattr
->typekind
) {
6600 hres
= get_iface_guid(tinfo2
, tattr
->tdescAlias
.u
.hreftype
, guid
);
6603 case TKIND_INTERFACE
:
6604 case TKIND_DISPATCH
:
6605 *guid
= tattr
->guid
;
6609 for (i
= 0; i
< tattr
->cImplTypes
; i
++)
6611 ITypeInfo_GetImplTypeFlags(tinfo2
, i
, &flags
);
6612 if (flags
& IMPLTYPEFLAG_FDEFAULT
)
6616 if (i
== tattr
->cImplTypes
)
6619 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo2
, i
, &href
);
6620 if (SUCCEEDED(hres
))
6621 hres
= get_iface_guid(tinfo2
, href
, guid
);
6625 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6626 hres
= E_UNEXPECTED
;
6629 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6630 ITypeInfo_Release(tinfo2
);
6634 /***********************************************************************
6635 * DispCallFunc (OLEAUT32.@)
6637 * Invokes a function of the specified calling convention, passing the
6638 * specified arguments and returns the result.
6641 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6642 * oVft [I] The offset in the vtable. See notes.
6643 * cc [I] Calling convention of the function to call.
6644 * vtReturn [I] The return type of the function.
6645 * cActuals [I] Number of parameters.
6646 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6647 * prgpvarg [I] The arguments to pass.
6648 * pvargResult [O] The return value of the function. Can be NULL.
6652 * Failure: HRESULT code.
6655 * The HRESULT return value of this function is not affected by the return
6656 * value of the user supplied function, which is returned in pvargResult.
6658 * If pvInstance is NULL then a non-object function is to be called and oVft
6659 * is the address of the function to call.
6661 * The cc parameter can be one of the following values:
6674 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6675 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6678 int argspos
= 0, stack_offset
;
6683 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6684 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6685 pvargResult
, V_VT(pvargResult
));
6687 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6689 FIXME("unsupported calling convention %d\n",cc
);
6690 return E_INVALIDARG
;
6693 /* maximum size for an argument is sizeof(VARIANT) */
6694 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6698 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6699 func
= vtable
[oVft
/sizeof(void *)];
6700 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6702 else func
= (void *)oVft
;
6708 args
[argspos
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6711 WARN("invalid return type %u\n", vtReturn
);
6713 return E_INVALIDARG
;
6718 for (i
= 0; i
< cActuals
; i
++)
6720 VARIANT
*arg
= prgpvarg
[i
];
6731 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6732 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6736 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6737 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6739 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6740 args
[argspos
++] = V_BOOL(arg
);
6743 args
[argspos
++] = V_UI4(arg
);
6746 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6754 call_method( func
, argspos
, args
, &stack_offset
);
6757 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6761 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6766 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6769 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6773 if (stack_offset
&& cc
== CC_STDCALL
)
6775 WARN( "stack pointer off by %d\n", stack_offset
);
6776 return DISP_E_BADCALLEE
;
6778 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6779 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6782 #elif defined(__x86_64__)
6788 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6789 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6790 pvargResult
, V_VT(pvargResult
));
6792 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6794 FIXME("unsupported calling convention %d\n",cc
);
6795 return E_INVALIDARG
;
6798 /* maximum size for an argument is sizeof(DWORD_PTR) */
6799 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6803 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6804 func
= vtable
[oVft
/sizeof(void *)];
6805 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6807 else func
= (void *)oVft
;
6813 args
[argspos
++] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6816 WARN("invalid return type %u\n", vtReturn
);
6818 return E_INVALIDARG
;
6823 for (i
= 0; i
< cActuals
; i
++)
6825 VARIANT
*arg
= prgpvarg
[i
];
6831 args
[argspos
++] = (ULONG_PTR
)arg
;
6833 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6834 args
[argspos
++] = V_BOOL(arg
);
6837 args
[argspos
++] = V_UI8(arg
);
6840 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6846 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
);
6850 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
);
6854 call_method( func
, argspos
, args
);
6857 V_UI8(pvargResult
) = call_method( func
, argspos
, args
);
6861 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6862 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6865 #elif defined(__arm__)
6879 int rcount
; /* 32-bit register index count */
6881 int scount
= 0; /* single-precision float register index count */
6882 int dcount
= 0; /* double-precision float register index count */
6885 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6886 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6888 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6890 FIXME("unsupported calling convention %d\n",cc
);
6891 return E_INVALIDARG
;
6899 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6900 func
= vtable
[oVft
/sizeof(void *)];
6901 regs
.r
[rcount
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6903 else func
= (void *)oVft
;
6905 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6906 /* first as it will need to be in the 'r' registers: */
6911 regs
.r
[rcount
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6914 WARN("invalid return type %u\n", vtReturn
);
6915 return E_INVALIDARG
;
6916 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6920 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6921 args
= heap_alloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 4 );
6923 for (i
= 0; i
< cActuals
; i
++)
6925 VARIANT
*arg
= prgpvarg
[i
];
6926 DWORD
*pdwarg
= (DWORD
*)(arg
); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6927 int ntemp
; /* Used for counting words split between registers and stack */
6933 case VT_R8
: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6936 dcount
= max( (scount
+ 1) / 2, dcount
);
6939 regs
.sd
.d
[dcount
++] = V_R8(arg
);
6943 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6944 memcpy( &args
[argspos
], &V_R8(arg
), sizeof(V_R8(arg
)) );
6945 argspos
+= sizeof(V_R8(arg
)) / sizeof(DWORD
);
6949 case VT_I8
: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6954 rcount
+= (rcount
% 2); /* align rcount to 8-byte register pair */
6955 memcpy( ®s
.r
[rcount
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6956 rcount
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6960 rcount
= 4; /* Make sure we flag that all 'r' regs are full */
6961 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6962 memcpy( &args
[argspos
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6963 argspos
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6966 case VT_DECIMAL
: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6968 /* 8-byte align 'r' and/or stack: */
6970 rcount
+= (rcount
% 2);
6974 argspos
+= (argspos
% 2);
6976 ntemp
= sizeof(*arg
) / sizeof(DWORD
);
6980 regs
.r
[rcount
++] = *pdwarg
++;
6982 args
[argspos
++] = *pdwarg
++;
6986 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6988 regs
.r
[rcount
++] = V_BOOL(arg
);
6990 args
[argspos
++] = V_BOOL(arg
);
6992 case VT_R4
: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6994 if (!(scount
% 2)) scount
= max( scount
, dcount
* 2 );
6996 regs
.sd
.s
[scount
++] = V_R4(arg
);
6998 args
[argspos
++] = V_UI4(arg
);
7003 regs
.r
[rcount
++] = V_UI4(arg
);
7005 args
[argspos
++] = V_UI4(arg
);
7008 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
7011 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 8-byte */
7015 case VT_EMPTY
: /* EMPTY = no return value */
7016 case VT_DECIMAL
: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
7018 call_method( func
, argspos
, args
, (DWORD
*)®s
);
7021 V_R4(pvargResult
) = call_float_method( func
, argspos
, args
, (DWORD
*)®s
);
7025 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, (DWORD
*)®s
);
7030 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
7033 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
7037 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
7038 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
7042 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7043 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
7048 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
7050 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
7053 #define INVBUF_ELEMENT_SIZE \
7054 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7055 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7056 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7057 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7058 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7059 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7060 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7061 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7063 static HRESULT WINAPI
ITypeInfo_fnInvoke(
7068 DISPPARAMS
*pDispParams
,
7069 VARIANT
*pVarResult
,
7070 EXCEPINFO
*pExcepInfo
,
7073 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7075 unsigned int var_index
;
7078 const TLBFuncDesc
*pFuncInfo
;
7081 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7082 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
7085 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7086 return DISP_E_MEMBERNOTFOUND
;
7090 ERR("NULL pDispParams not allowed\n");
7091 return E_INVALIDARG
;
7094 dump_DispParms(pDispParams
);
7096 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7098 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7099 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7100 return E_INVALIDARG
;
7103 /* we do this instead of using GetFuncDesc since it will return a fake
7104 * FUNCDESC for dispinterfaces and we want the real function description */
7105 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7106 pFuncInfo
= &This
->funcdescs
[fdc
];
7107 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7108 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7109 !func_restricted( &pFuncInfo
->funcdesc
))
7113 if (fdc
< This
->typeattr
.cFuncs
) {
7114 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7118 TRACE("invoking:\n");
7119 dump_TLBFuncDescOne(pFuncInfo
);
7122 switch (func_desc
->funckind
) {
7123 case FUNC_PUREVIRTUAL
:
7124 case FUNC_VIRTUAL
: {
7125 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7127 VARIANT retval
; /* pointer for storing byref retvals in */
7128 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7129 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7130 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7131 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7132 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7133 UINT vargs_converted
=0;
7137 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7139 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7141 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7142 hres
= DISP_E_PARAMNOTFOUND
;
7147 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7149 ERR("functions with the vararg attribute do not support named arguments\n");
7150 hres
= DISP_E_NONAMEDARGS
;
7154 for (i
= 0; i
< func_desc
->cParams
; i
++)
7156 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7157 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7162 TRACE("changing args\n");
7163 for (i
= 0; i
< func_desc
->cParams
; i
++)
7165 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7166 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7167 VARIANTARG
*src_arg
;
7169 if (wParamFlags
& PARAMFLAG_FLCID
)
7172 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7174 V_I4(arg
) = This
->pTypeLib
->lcid
;
7183 for (j
= 0; j
< cNamedArgs
; j
++)
7184 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7186 src_arg
= &pDispParams
->rgvarg
[j
];
7191 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7193 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7197 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7199 /* under most conditions the caller is not allowed to
7200 * pass in a dispparam arg in the index of what would be
7201 * the retval parameter. however, there is an exception
7202 * where the extra parameter is used in an extra
7203 * IDispatch::Invoke below */
7204 if ((i
< pDispParams
->cArgs
) &&
7205 ((func_desc
->cParams
!= 1) || !pVarResult
||
7206 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7208 hres
= DISP_E_BADPARAMCOUNT
;
7212 /* note: this check is placed so that if the caller passes
7213 * in a VARIANTARG for the retval we just ignore it, like
7215 if (i
== func_desc
->cParams
- 1)
7218 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7219 memset(arg
, 0, sizeof(*arg
));
7220 V_VT(arg
) = rgvt
[i
];
7221 memset(&retval
, 0, sizeof(retval
));
7222 V_BYREF(arg
) = &retval
;
7226 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7227 hres
= E_UNEXPECTED
;
7231 else if (src_arg
&& !((wParamFlags
& PARAMFLAG_FOPT
) &&
7232 V_VT(src_arg
) == VT_ERROR
&& V_ERROR(src_arg
) == DISP_E_PARAMNOTFOUND
))
7234 TRACE("%s\n", debugstr_variant(src_arg
));
7236 if(rgvt
[i
]!=V_VT(src_arg
))
7238 if (rgvt
[i
] == VT_VARIANT
)
7239 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7240 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7242 if (rgvt
[i
] == V_VT(src_arg
))
7243 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7246 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7247 if (wParamFlags
& PARAMFLAG_FIN
)
7248 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7249 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7251 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7253 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7256 SAFEARRAYBOUND bound
;
7260 bound
.cElements
= pDispParams
->cArgs
-i
;
7261 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7263 ERR("SafeArrayCreate failed\n");
7266 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7269 ERR("SafeArrayAccessData failed with %x\n", hres
);
7270 SafeArrayDestroy(a
);
7273 for (j
= 0; j
< bound
.cElements
; j
++)
7274 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7275 hres
= SafeArrayUnaccessData(a
);
7278 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7279 SafeArrayDestroy(a
);
7282 if (rgvt
[i
] & VT_BYREF
)
7283 V_BYREF(&rgvarg
[i
]) = &a
;
7285 V_ARRAY(&rgvarg
[i
]) = a
;
7286 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7288 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7290 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7291 if (wParamFlags
& PARAMFLAG_FIN
)
7292 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7294 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7295 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7296 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7298 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7300 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7301 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7305 /* FIXME: this doesn't work for VT_BYREF arguments if
7306 * they are not the same type as in the paramdesc */
7307 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7308 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7309 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7314 ERR("failed to convert param %d to %s from %s\n", i
,
7315 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7318 prgpvarg
[i
] = &rgvarg
[i
];
7322 prgpvarg
[i
] = src_arg
;
7325 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7326 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7327 && V_UNKNOWN(prgpvarg
[i
])) {
7328 IUnknown
*userdefined_iface
;
7331 if (tdesc
->vt
== VT_PTR
)
7332 tdesc
= tdesc
->u
.lptdesc
;
7334 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->u
.hreftype
, &guid
);
7338 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7340 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7344 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7345 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7348 else if (wParamFlags
& PARAMFLAG_FOPT
)
7351 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7352 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7354 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7360 VARIANTARG
*missing_arg
;
7361 /* if the function wants a pointer to a variant then
7362 * set that up, otherwise just pass the VT_ERROR in
7363 * the argument by value */
7364 if (rgvt
[i
] & VT_BYREF
)
7366 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7367 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7368 V_VARIANTREF(arg
) = missing_arg
;
7372 V_VT(missing_arg
) = VT_ERROR
;
7373 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7378 hres
= DISP_E_BADPARAMCOUNT
;
7382 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7384 /* VT_VOID is a special case for return types, so it is not
7385 * handled in the general function */
7386 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7387 V_VT(&varresult
) = VT_EMPTY
;
7390 V_VT(&varresult
) = 0;
7391 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7392 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7395 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7396 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7397 prgpvarg
, &varresult
);
7399 vargs_converted
= 0;
7401 for (i
= 0; i
< func_desc
->cParams
; i
++)
7403 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7404 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7406 if (wParamFlags
& PARAMFLAG_FLCID
)
7408 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7410 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7414 VariantInit(pVarResult
);
7415 /* deref return value */
7416 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7419 VARIANT_ClearInd(prgpvarg
[i
]);
7421 else if (vargs_converted
< pDispParams
->cArgs
)
7423 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7424 if (wParamFlags
& PARAMFLAG_FOUT
)
7426 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7428 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7432 ERR("failed to convert param %d to vt %d\n", i
,
7433 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7438 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7439 func_desc
->cParamsOpt
< 0 &&
7440 i
== func_desc
->cParams
-1)
7442 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7445 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7448 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7451 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7454 ERR("SafeArrayAccessData failed with %x\n", hres
);
7457 for (j
= 0; j
<= ubound
; j
++)
7458 VariantClear(&v
[j
]);
7459 hres
= SafeArrayUnaccessData(a
);
7462 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7466 VariantClear(&rgvarg
[i
]);
7469 else if (wParamFlags
& PARAMFLAG_FOPT
)
7471 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7472 VariantClear(&rgvarg
[i
]);
7475 VariantClear(&missing_arg
[i
]);
7478 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7480 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7481 hres
= DISP_E_EXCEPTION
;
7484 IErrorInfo
*pErrorInfo
;
7485 pExcepInfo
->scode
= V_ERROR(&varresult
);
7486 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7488 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7489 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7490 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7491 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7493 IErrorInfo_Release(pErrorInfo
);
7497 if (V_VT(&varresult
) != VT_ERROR
)
7499 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7503 VariantClear(pVarResult
);
7504 *pVarResult
= varresult
;
7507 VariantClear(&varresult
);
7510 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7511 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7512 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7513 (pDispParams
->cArgs
!= 0))
7515 if (V_VT(pVarResult
) == VT_DISPATCH
)
7517 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7518 /* Note: not VariantClear; we still need the dispatch
7519 * pointer to be valid */
7520 VariantInit(pVarResult
);
7521 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7522 GetSystemDefaultLCID(), wFlags
,
7523 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7524 IDispatch_Release(pDispatch
);
7528 VariantClear(pVarResult
);
7529 hres
= DISP_E_NOTACOLLECTION
;
7537 case FUNC_DISPATCH
: {
7540 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7541 if (SUCCEEDED(hres
)) {
7542 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7543 hres
= IDispatch_Invoke(
7544 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7545 pVarResult
,pExcepInfo
,pArgErr
7548 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7549 IDispatch_Release(disp
);
7551 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7555 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7560 TRACE("-- 0x%08x\n", hres
);
7563 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7566 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7567 if(FAILED(hres
)) return hres
;
7569 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7570 dump_VARDESC(var_desc
);
7571 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7575 /* not found, look for it in inherited interfaces */
7576 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7577 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7578 if(This
->impltypes
) {
7579 /* recursive search */
7581 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7582 if(SUCCEEDED(hres
)){
7583 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7584 ITypeInfo_Release(pTInfo
);
7587 WARN("Could not search inherited interface!\n");
7590 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7591 return DISP_E_MEMBERNOTFOUND
;
7594 /* ITypeInfo::GetDocumentation
7596 * Retrieves the documentation string, the complete Help file name and path,
7597 * and the context ID for the Help topic for a specified type description.
7599 * (Can be tested by the Visual Basic Editor in Word for instance.)
7601 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7602 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7603 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7605 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7606 const TLBFuncDesc
*pFDesc
;
7607 const TLBVarDesc
*pVDesc
;
7608 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7609 " HelpContext(%p) HelpFile(%p)\n",
7610 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7611 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7613 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7615 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7617 *pdwHelpContext
=This
->dwHelpContext
;
7619 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7621 }else {/* for a member */
7622 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7625 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7627 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7629 *pdwHelpContext
=pFDesc
->helpcontext
;
7631 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7634 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
7637 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7639 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7641 *pdwHelpContext
=pVDesc
->HelpContext
;
7643 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7648 if(This
->impltypes
&&
7649 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7650 /* recursive search */
7653 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7654 if(SUCCEEDED(result
)) {
7655 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7656 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7657 ITypeInfo_Release(pTInfo
);
7660 WARN("Could not search inherited interface!\n");
7663 WARN("member %d not found\n", memid
);
7664 return TYPE_E_ELEMENTNOTFOUND
;
7667 /* ITypeInfo::GetDllEntry
7669 * Retrieves a description or specification of an entry point for a function
7672 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7673 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7676 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7677 const TLBFuncDesc
*pFDesc
;
7679 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7681 if (pBstrDllName
) *pBstrDllName
= NULL
;
7682 if (pBstrName
) *pBstrName
= NULL
;
7683 if (pwOrdinal
) *pwOrdinal
= 0;
7685 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7686 return TYPE_E_BADMODULEKIND
;
7688 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7690 dump_TypeInfo(This
);
7692 dump_TLBFuncDescOne(pFDesc
);
7695 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7697 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7699 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7707 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7710 return TYPE_E_ELEMENTNOTFOUND
;
7713 /* internal function to make the inherited interfaces' methods appear
7714 * part of the interface */
7715 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7716 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7718 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7721 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7723 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7725 ITypeInfo
*pSubTypeInfo
;
7727 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7731 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7733 ITypeInfo_Release(pSubTypeInfo
);
7737 *hRefType
-= DISPATCH_HREF_OFFSET
;
7739 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7740 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7745 struct search_res_tlb_params
7751 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7753 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7754 static const WCHAR formatW
[] = {'\\','%','d',0};
7755 WCHAR szPath
[MAX_PATH
+1];
7756 ITypeLib
*pTLib
= NULL
;
7760 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7763 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7766 if (snprintfW(szPath
+ len
, ARRAY_SIZE(szPath
) - len
, formatW
, LOWORD(lpszName
)) < 0)
7769 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7772 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7773 if (IsEqualGUID(params
->guid
, impl
->guid
))
7775 params
->pTLib
= pTLib
;
7776 return FALSE
; /* stop enumeration */
7778 ITypeLib_Release(pTLib
);
7784 /* ITypeInfo::GetRefTypeInfo
7786 * If a type description references other type descriptions, it retrieves
7787 * the referenced type descriptions.
7789 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7792 ITypeInfo
**ppTInfo
)
7794 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7795 HRESULT result
= E_FAIL
;
7798 return E_INVALIDARG
;
7800 if ((INT
)hRefType
< 0) {
7801 ITypeInfoImpl
*pTypeInfoImpl
;
7803 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7804 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7805 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7806 return TYPE_E_ELEMENTNOTFOUND
;
7808 /* when we meet a DUAL typeinfo, we must create the alternate
7811 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7813 *pTypeInfoImpl
= *This
;
7814 pTypeInfoImpl
->ref
= 0;
7815 list_init(&pTypeInfoImpl
->custdata_list
);
7817 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7818 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7820 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7822 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7823 /* the AddRef implicitly adds a reference to the parent typelib, which
7824 * stops the copied data from being destroyed until the new typeinfo's
7825 * refcount goes to zero, but we need to signal to the new instance to
7826 * not free its data structures when it is destroyed */
7827 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7829 ITypeInfo_AddRef(*ppTInfo
);
7832 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7833 (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7835 HREFTYPE href_dispatch
= hRefType
;
7836 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7838 TLBRefType
*ref_type
;
7839 ITypeLib
*pTLib
= NULL
;
7842 if(!(hRefType
& 0x1)){
7843 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7845 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7848 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7849 ITypeInfo_AddRef(*ppTInfo
);
7855 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7857 if(ref_type
->reference
== (hRefType
& (~0x3)))
7860 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7862 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7866 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7868 TRACE("internal reference\n");
7869 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7871 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7872 TRACE("typeinfo in imported typelib that is already loaded\n");
7873 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7874 ITypeLib_AddRef(pTLib
);
7877 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
7878 struct search_res_tlb_params params
;
7881 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7883 /* Search in resource table */
7884 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
7885 params
.pTLib
= NULL
;
7886 EnumResourceNamesW(NULL
, TYPELIBW
, search_res_tlb
, (LONG_PTR
)¶ms
);
7887 pTLib
= params
.pTLib
;
7892 /* Search on disk */
7893 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7894 ref_type
->pImpTLInfo
->wVersionMajor
,
7895 ref_type
->pImpTLInfo
->wVersionMinor
,
7896 This
->pTypeLib
->syskind
,
7897 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7899 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7901 result
= LoadTypeLib(libnam
, &pTLib
);
7902 SysFreeString(libnam
);
7905 if(SUCCEEDED(result
)) {
7906 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7907 ITypeLib_AddRef(pTLib
);
7911 if(SUCCEEDED(result
)) {
7912 if(ref_type
->index
== TLB_REF_USE_GUID
)
7913 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7915 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7918 ITypeLib_Release(pTLib
);
7922 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7923 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7927 /* ITypeInfo::AddressOfMember
7929 * Retrieves the addresses of static functions or variables, such as those
7932 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7933 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7935 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7941 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7943 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7947 module
= LoadLibraryW(dll
);
7950 ERR("couldn't load %s\n", debugstr_w(dll
));
7952 SysFreeString(entry
);
7953 return STG_E_FILENOTFOUND
;
7955 /* FIXME: store library somewhere where we can free it */
7960 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7961 entryA
= heap_alloc(len
);
7962 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7964 *ppv
= GetProcAddress(module
, entryA
);
7966 ERR("function not found %s\n", debugstr_a(entryA
));
7972 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7974 ERR("function not found %d\n", ordinal
);
7978 SysFreeString(entry
);
7981 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7986 /* ITypeInfo::CreateInstance
7988 * Creates a new instance of a type that describes a component object class
7991 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7992 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7994 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7998 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
8004 WARN("Not able to aggregate\n");
8005 return CLASS_E_NOAGGREGATION
;
8008 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
8009 if(FAILED(hr
)) return hr
;
8011 if(pTA
->typekind
!= TKIND_COCLASS
)
8013 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
8019 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
8022 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
8023 TRACE("GetActiveObject rets %08x\n", hr
);
8026 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
8027 IUnknown_Release(pUnk
);
8032 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
8033 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8037 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8041 /* ITypeInfo::GetMops
8043 * Retrieves marshalling information.
8045 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
8048 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8049 FIXME("(%p %d) stub!\n", This
, memid
);
8054 /* ITypeInfo::GetContainingTypeLib
8056 * Retrieves the containing type library and the index of the type description
8057 * within that type library.
8059 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8060 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8062 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8064 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8066 *pIndex
=This
->index
;
8067 TRACE("returning pIndex=%d\n", *pIndex
);
8071 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8072 ITypeLib_AddRef(*ppTLib
);
8073 TRACE("returning ppTLib=%p\n", *ppTLib
);
8079 /* ITypeInfo::ReleaseTypeAttr
8081 * Releases a TYPEATTR previously returned by Get
8084 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8085 TYPEATTR
* pTypeAttr
)
8087 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8088 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8089 heap_free(pTypeAttr
);
8092 /* ITypeInfo::ReleaseFuncDesc
8094 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8096 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8098 FUNCDESC
*pFuncDesc
)
8100 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8103 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8105 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8106 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8107 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8109 SysFreeString((BSTR
)pFuncDesc
);
8112 /* ITypeInfo::ReleaseVarDesc
8114 * Releases a VARDESC previously returned by GetVarDesc.
8116 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8119 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8120 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8122 TLB_FreeVarDesc(pVarDesc
);
8125 /* ITypeInfo2::GetTypeKind
8127 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8130 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8131 TYPEKIND
*pTypeKind
)
8133 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8134 *pTypeKind
= This
->typeattr
.typekind
;
8135 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8139 /* ITypeInfo2::GetTypeFlags
8141 * Returns the type flags without any allocations. This returns a DWORD type
8142 * flag, which expands the type flags without growing the TYPEATTR (type
8146 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8148 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8149 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8150 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
8154 /* ITypeInfo2::GetFuncIndexOfMemId
8155 * Binds to a specific member based on a known DISPID, where the member name
8156 * is not known (for example, when binding to a default member).
8159 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8160 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8162 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8166 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8167 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8168 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8171 if(fdc
< This
->typeattr
.cFuncs
) {
8175 result
= TYPE_E_ELEMENTNOTFOUND
;
8177 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
8178 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8182 /* TypeInfo2::GetVarIndexOfMemId
8184 * Binds to a specific member based on a known DISPID, where the member name
8185 * is not known (for example, when binding to a default member).
8188 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8189 MEMBERID memid
, UINT
*pVarIndex
)
8191 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8192 TLBVarDesc
*pVarInfo
;
8194 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8196 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
8198 return TYPE_E_ELEMENTNOTFOUND
;
8200 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8205 /* ITypeInfo2::GetCustData
8207 * Gets the custom data
8209 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8214 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8215 TLBCustData
*pCData
;
8217 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8219 if(!guid
|| !pVarVal
)
8220 return E_INVALIDARG
;
8222 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8224 VariantInit( pVarVal
);
8226 VariantCopy( pVarVal
, &pCData
->data
);
8228 VariantClear( pVarVal
);
8232 /* ITypeInfo2::GetFuncCustData
8234 * Gets the custom data
8236 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8242 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8243 TLBCustData
*pCData
;
8244 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8246 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8248 if(index
>= This
->typeattr
.cFuncs
)
8249 return TYPE_E_ELEMENTNOTFOUND
;
8251 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8253 return TYPE_E_ELEMENTNOTFOUND
;
8255 VariantInit(pVarVal
);
8256 VariantCopy(pVarVal
, &pCData
->data
);
8261 /* ITypeInfo2::GetParamCustData
8263 * Gets the custom data
8265 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8272 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8273 TLBCustData
*pCData
;
8274 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8276 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8277 debugstr_guid(guid
), pVarVal
);
8279 if(indexFunc
>= This
->typeattr
.cFuncs
)
8280 return TYPE_E_ELEMENTNOTFOUND
;
8282 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8283 return TYPE_E_ELEMENTNOTFOUND
;
8285 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8287 return TYPE_E_ELEMENTNOTFOUND
;
8289 VariantInit(pVarVal
);
8290 VariantCopy(pVarVal
, &pCData
->data
);
8295 /* ITypeInfo2::GetVarCustData
8297 * Gets the custom data
8299 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8305 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8306 TLBCustData
*pCData
;
8307 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8309 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8311 if(index
>= This
->typeattr
.cVars
)
8312 return TYPE_E_ELEMENTNOTFOUND
;
8314 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8316 return TYPE_E_ELEMENTNOTFOUND
;
8318 VariantInit(pVarVal
);
8319 VariantCopy(pVarVal
, &pCData
->data
);
8324 /* ITypeInfo2::GetImplCustData
8326 * Gets the custom data
8328 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8334 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8335 TLBCustData
*pCData
;
8336 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8338 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8340 if(index
>= This
->typeattr
.cImplTypes
)
8341 return TYPE_E_ELEMENTNOTFOUND
;
8343 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8345 return TYPE_E_ELEMENTNOTFOUND
;
8347 VariantInit(pVarVal
);
8348 VariantCopy(pVarVal
, &pCData
->data
);
8353 /* ITypeInfo2::GetDocumentation2
8355 * Retrieves the documentation string, the complete Help file name and path,
8356 * the localization context to use, and the context ID for the library Help
8357 * topic in the Help file.
8360 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8364 BSTR
*pbstrHelpString
,
8365 DWORD
*pdwHelpStringContext
,
8366 BSTR
*pbstrHelpStringDll
)
8368 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8369 const TLBFuncDesc
*pFDesc
;
8370 const TLBVarDesc
*pVDesc
;
8371 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8372 "HelpStringContext(%p) HelpStringDll(%p)\n",
8373 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8374 pbstrHelpStringDll
);
8375 /* the help string should be obtained from the helpstringdll,
8376 * using the _DLLGetDocumentation function, based on the supplied
8377 * lcid. Nice to do sometime...
8379 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8381 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8382 if(pdwHelpStringContext
)
8383 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8384 if(pbstrHelpStringDll
)
8385 *pbstrHelpStringDll
=
8386 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8388 }else {/* for a member */
8389 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
8392 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8393 if(pdwHelpStringContext
)
8394 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8395 if(pbstrHelpStringDll
)
8396 *pbstrHelpStringDll
=
8397 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8400 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
8403 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8404 if(pdwHelpStringContext
)
8405 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8406 if(pbstrHelpStringDll
)
8407 *pbstrHelpStringDll
=
8408 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8412 return TYPE_E_ELEMENTNOTFOUND
;
8415 /* ITypeInfo2::GetAllCustData
8417 * Gets all custom data items for the Type info.
8420 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8422 CUSTDATA
*pCustData
)
8424 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8426 TRACE("%p %p\n", This
, pCustData
);
8428 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8431 /* ITypeInfo2::GetAllFuncCustData
8433 * Gets all custom data items for the specified Function
8436 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8439 CUSTDATA
*pCustData
)
8441 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8442 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8444 TRACE("%p %u %p\n", This
, index
, pCustData
);
8446 if(index
>= This
->typeattr
.cFuncs
)
8447 return TYPE_E_ELEMENTNOTFOUND
;
8449 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8452 /* ITypeInfo2::GetAllParamCustData
8454 * Gets all custom data items for the Functions
8457 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8458 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8460 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8461 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8463 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8465 if(indexFunc
>= This
->typeattr
.cFuncs
)
8466 return TYPE_E_ELEMENTNOTFOUND
;
8468 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8469 return TYPE_E_ELEMENTNOTFOUND
;
8471 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8474 /* ITypeInfo2::GetAllVarCustData
8476 * Gets all custom data items for the specified Variable
8479 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8480 UINT index
, CUSTDATA
*pCustData
)
8482 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8483 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8485 TRACE("%p %u %p\n", This
, index
, pCustData
);
8487 if(index
>= This
->typeattr
.cVars
)
8488 return TYPE_E_ELEMENTNOTFOUND
;
8490 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8493 /* ITypeInfo2::GetAllImplCustData
8495 * Gets all custom data items for the specified implementation type
8498 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8501 CUSTDATA
*pCustData
)
8503 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8504 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8506 TRACE("%p %u %p\n", This
, index
, pCustData
);
8508 if(index
>= This
->typeattr
.cImplTypes
)
8509 return TYPE_E_ELEMENTNOTFOUND
;
8511 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8514 static const ITypeInfo2Vtbl tinfvt
=
8517 ITypeInfo_fnQueryInterface
,
8519 ITypeInfo_fnRelease
,
8521 ITypeInfo_fnGetTypeAttr
,
8522 ITypeInfo_fnGetTypeComp
,
8523 ITypeInfo_fnGetFuncDesc
,
8524 ITypeInfo_fnGetVarDesc
,
8525 ITypeInfo_fnGetNames
,
8526 ITypeInfo_fnGetRefTypeOfImplType
,
8527 ITypeInfo_fnGetImplTypeFlags
,
8528 ITypeInfo_fnGetIDsOfNames
,
8530 ITypeInfo_fnGetDocumentation
,
8531 ITypeInfo_fnGetDllEntry
,
8532 ITypeInfo_fnGetRefTypeInfo
,
8533 ITypeInfo_fnAddressOfMember
,
8534 ITypeInfo_fnCreateInstance
,
8535 ITypeInfo_fnGetMops
,
8536 ITypeInfo_fnGetContainingTypeLib
,
8537 ITypeInfo_fnReleaseTypeAttr
,
8538 ITypeInfo_fnReleaseFuncDesc
,
8539 ITypeInfo_fnReleaseVarDesc
,
8541 ITypeInfo2_fnGetTypeKind
,
8542 ITypeInfo2_fnGetTypeFlags
,
8543 ITypeInfo2_fnGetFuncIndexOfMemId
,
8544 ITypeInfo2_fnGetVarIndexOfMemId
,
8545 ITypeInfo2_fnGetCustData
,
8546 ITypeInfo2_fnGetFuncCustData
,
8547 ITypeInfo2_fnGetParamCustData
,
8548 ITypeInfo2_fnGetVarCustData
,
8549 ITypeInfo2_fnGetImplTypeCustData
,
8550 ITypeInfo2_fnGetDocumentation2
,
8551 ITypeInfo2_fnGetAllCustData
,
8552 ITypeInfo2_fnGetAllFuncCustData
,
8553 ITypeInfo2_fnGetAllParamCustData
,
8554 ITypeInfo2_fnGetAllVarCustData
,
8555 ITypeInfo2_fnGetAllImplTypeCustData
,
8558 /******************************************************************************
8559 * CreateDispTypeInfo [OLEAUT32.31]
8561 * Build type information for an object so it can be called through an
8562 * IDispatch interface.
8565 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8566 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8569 * This call allows an objects methods to be accessed through IDispatch, by
8570 * building an ITypeInfo object that IDispatch can use to call through.
8572 HRESULT WINAPI
CreateDispTypeInfo(
8573 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8574 LCID lcid
, /* [I] Locale Id */
8575 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8577 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8578 ITypeLibImpl
*pTypeLibImpl
;
8579 unsigned int param
, func
;
8580 TLBFuncDesc
*pFuncDesc
;
8584 pTypeLibImpl
= TypeLibImpl_Constructor();
8585 if (!pTypeLibImpl
) return E_FAIL
;
8587 pTypeLibImpl
->TypeInfoCount
= 2;
8588 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8590 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8591 pTIIface
->pTypeLib
= pTypeLibImpl
;
8592 pTIIface
->index
= 0;
8593 pTIIface
->Name
= NULL
;
8594 pTIIface
->dwHelpContext
= -1;
8595 pTIIface
->guid
= NULL
;
8596 pTIIface
->typeattr
.lcid
= lcid
;
8597 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8598 pTIIface
->typeattr
.wMajorVerNum
= 0;
8599 pTIIface
->typeattr
.wMinorVerNum
= 0;
8600 pTIIface
->typeattr
.cbAlignment
= 2;
8601 pTIIface
->typeattr
.cbSizeInstance
= -1;
8602 pTIIface
->typeattr
.cbSizeVft
= -1;
8603 pTIIface
->typeattr
.cFuncs
= 0;
8604 pTIIface
->typeattr
.cImplTypes
= 0;
8605 pTIIface
->typeattr
.cVars
= 0;
8606 pTIIface
->typeattr
.wTypeFlags
= 0;
8607 pTIIface
->hreftype
= 0;
8609 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8610 pFuncDesc
= pTIIface
->funcdescs
;
8611 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8612 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8613 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8614 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8615 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8616 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8617 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8618 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8619 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8620 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8621 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8622 pFuncDesc
->funcdesc
.cScodes
= 0;
8623 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8624 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8625 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8626 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8627 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8628 md
->cArgs
* sizeof(ELEMDESC
));
8629 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8630 for(param
= 0; param
< md
->cArgs
; param
++) {
8631 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8632 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8634 pFuncDesc
->helpcontext
= 0;
8635 pFuncDesc
->HelpStringContext
= 0;
8636 pFuncDesc
->HelpString
= NULL
;
8637 pFuncDesc
->Entry
= NULL
;
8638 list_init(&pFuncDesc
->custdata_list
);
8639 pTIIface
->typeattr
.cFuncs
++;
8643 dump_TypeInfo(pTIIface
);
8645 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8646 pTIClass
->pTypeLib
= pTypeLibImpl
;
8647 pTIClass
->index
= 1;
8648 pTIClass
->Name
= NULL
;
8649 pTIClass
->dwHelpContext
= -1;
8650 pTIClass
->guid
= NULL
;
8651 pTIClass
->typeattr
.lcid
= lcid
;
8652 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8653 pTIClass
->typeattr
.wMajorVerNum
= 0;
8654 pTIClass
->typeattr
.wMinorVerNum
= 0;
8655 pTIClass
->typeattr
.cbAlignment
= 2;
8656 pTIClass
->typeattr
.cbSizeInstance
= -1;
8657 pTIClass
->typeattr
.cbSizeVft
= -1;
8658 pTIClass
->typeattr
.cFuncs
= 0;
8659 pTIClass
->typeattr
.cImplTypes
= 1;
8660 pTIClass
->typeattr
.cVars
= 0;
8661 pTIClass
->typeattr
.wTypeFlags
= 0;
8662 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8664 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8666 ref
= heap_alloc_zero(sizeof(*ref
));
8667 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8668 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8670 dump_TypeInfo(pTIClass
);
8672 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8674 ITypeInfo_AddRef(*pptinfo
);
8675 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8681 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8683 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8685 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8688 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8690 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8692 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8695 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8697 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8699 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8702 static HRESULT WINAPI
ITypeComp_fnBind(
8707 ITypeInfo
** ppTInfo
,
8708 DESCKIND
* pDescKind
,
8711 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8712 const TLBFuncDesc
*pFDesc
;
8713 const TLBVarDesc
*pVDesc
;
8714 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8717 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8719 *pDescKind
= DESCKIND_NONE
;
8720 pBindPtr
->lpfuncdesc
= NULL
;
8723 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8724 pFDesc
= &This
->funcdescs
[fdc
];
8725 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8726 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8729 /* name found, but wrong flags */
8730 hr
= TYPE_E_TYPEMISMATCH
;
8734 if (fdc
< This
->typeattr
.cFuncs
)
8736 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8738 &pBindPtr
->lpfuncdesc
,
8739 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8742 *pDescKind
= DESCKIND_FUNCDESC
;
8743 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8744 ITypeInfo_AddRef(*ppTInfo
);
8747 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, szName
);
8749 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8752 *pDescKind
= DESCKIND_VARDESC
;
8753 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8754 ITypeInfo_AddRef(*ppTInfo
);
8759 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8760 /* recursive search */
8764 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8767 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8768 ITypeInfo_Release(pTInfo
);
8772 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8773 ITypeComp_Release(pTComp
);
8774 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8775 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8777 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8778 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8779 SysFreeString((BSTR
)tmp
);
8783 WARN("Could not search inherited interface!\n");
8785 if (hr
== DISP_E_MEMBERNOTFOUND
)
8787 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8791 static HRESULT WINAPI
ITypeComp_fnBindType(
8795 ITypeInfo
** ppTInfo
,
8796 ITypeComp
** ppTComp
)
8798 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8800 /* strange behaviour (does nothing) but like the
8803 if (!ppTInfo
|| !ppTComp
)
8812 static const ITypeCompVtbl tcompvt
=
8815 ITypeComp_fnQueryInterface
,
8817 ITypeComp_fnRelease
,
8820 ITypeComp_fnBindType
8823 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8824 ICreateTypeLib2
** ppctlib
)
8829 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8831 if (!szFile
) return E_INVALIDARG
;
8833 This
= TypeLibImpl_Constructor();
8835 return E_OUTOFMEMORY
;
8837 This
->lcid
= GetSystemDefaultLCID();
8838 This
->syskind
= syskind
;
8839 This
->ptr_size
= get_ptr_size(syskind
);
8841 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8843 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8844 return E_OUTOFMEMORY
;
8846 lstrcpyW(This
->path
, szFile
);
8848 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8849 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8853 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8854 REFIID riid
, void **object
)
8856 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8858 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8861 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8863 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8865 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8868 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8870 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8872 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8875 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8876 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8878 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8879 ITypeInfoImpl
*info
;
8882 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8884 if (!ctinfo
|| !name
)
8885 return E_INVALIDARG
;
8887 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8889 return TYPE_E_NAMECONFLICT
;
8891 if (This
->typeinfos
)
8892 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8893 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8895 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8897 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8899 info
->pTypeLib
= This
;
8900 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8901 info
->index
= This
->TypeInfoCount
;
8902 info
->typeattr
.typekind
= kind
;
8903 info
->typeattr
.cbAlignment
= 4;
8905 switch (info
->typeattr
.typekind
) {
8907 case TKIND_INTERFACE
:
8908 case TKIND_DISPATCH
:
8910 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
8914 info
->typeattr
.cbSizeInstance
= 0;
8917 info
->typeattr
.cbSizeInstance
= 2;
8920 info
->typeattr
.cbSizeInstance
= -0x75;
8923 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
8924 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
8928 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8929 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8931 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8935 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8937 ++This
->TypeInfoCount
;
8942 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8945 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8947 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8950 return E_INVALIDARG
;
8952 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8957 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8958 WORD majorVerNum
, WORD minorVerNum
)
8960 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8962 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8964 This
->ver_major
= majorVerNum
;
8965 This
->ver_minor
= minorVerNum
;
8970 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8973 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8975 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8977 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8982 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8985 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8987 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8990 return E_INVALIDARG
;
8992 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8997 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8998 LPOLESTR helpFileName
)
9000 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9002 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
9005 return E_INVALIDARG
;
9007 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
9012 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
9015 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9017 TRACE("%p %d\n", This
, helpContext
);
9019 This
->dwHelpContext
= helpContext
;
9024 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
9027 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9029 TRACE("%p %x\n", This
, lcid
);
9031 This
->set_lcid
= lcid
;
9036 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9039 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9041 TRACE("%p %x\n", This
, libFlags
);
9043 This
->libflags
= libFlags
;
9048 typedef struct tagWMSFT_SegContents
{
9051 } WMSFT_SegContents
;
9053 typedef struct tagWMSFT_TLBFile
{
9055 WMSFT_SegContents typeinfo_seg
;
9056 WMSFT_SegContents impfile_seg
;
9057 WMSFT_SegContents impinfo_seg
;
9058 WMSFT_SegContents ref_seg
;
9059 WMSFT_SegContents guidhash_seg
;
9060 WMSFT_SegContents guid_seg
;
9061 WMSFT_SegContents namehash_seg
;
9062 WMSFT_SegContents name_seg
;
9063 WMSFT_SegContents string_seg
;
9064 WMSFT_SegContents typdesc_seg
;
9065 WMSFT_SegContents arraydesc_seg
;
9066 WMSFT_SegContents custdata_seg
;
9067 WMSFT_SegContents cdguids_seg
;
9069 WMSFT_SegContents aux_seg
;
9072 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9073 WMSFT_TLBFile
*file
)
9079 file
->string_seg
.len
= 0;
9080 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9083 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9085 return E_UNEXPECTED
;
9087 size
+= sizeof(INT16
);
9089 size
= (size
+ 4) & ~0x3;
9093 file
->string_seg
.len
+= size
;
9095 /* temporarily use str->offset to store the length of the aligned,
9096 * converted string */
9100 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
9103 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9106 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
9107 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9109 heap_free(file
->string_seg
.data
);
9110 return E_UNEXPECTED
;
9113 *((INT16
*)data
) = size
;
9115 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9119 str
->offset
= last_offs
;
9126 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9127 WMSFT_TLBFile
*file
)
9132 MSFT_NameIntro
*last_intro
= NULL
;
9134 file
->header
.nametablecount
= 0;
9135 file
->header
.nametablechars
= 0;
9137 file
->name_seg
.len
= 0;
9138 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9141 size
= strlenW(str
->str
);
9142 file
->header
.nametablechars
+= size
;
9143 file
->header
.nametablecount
++;
9145 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9147 return E_UNEXPECTED
;
9149 size
+= sizeof(MSFT_NameIntro
);
9151 size
= (size
+ 4) & ~0x3;
9155 file
->name_seg
.len
+= size
;
9157 /* temporarily use str->offset to store the length of the aligned,
9158 * converted string */
9162 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9163 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
9166 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9168 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9170 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
9171 data
+ sizeof(MSFT_NameIntro
),
9172 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9174 heap_free(file
->name_seg
.data
);
9175 return E_UNEXPECTED
;
9177 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9179 intro
->hreftype
= -1; /* TODO? */
9180 intro
->namelen
= size
& 0xFF;
9181 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9182 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9183 intro
->namelen
|= hash
<< 16;
9184 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9185 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9187 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9188 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9190 /* update str->offset to actual value to use in other
9191 * compilation functions that require positions within
9192 * the string table */
9196 str
->offset
= last_offs
;
9201 last_intro
->hreftype
= 0; /* last one is 0? */
9206 static inline int hash_guid(GUID
*guid
)
9210 for (i
= 0; i
< 8; i
++)
9211 hash
^= ((const short *)guid
)[i
];
9216 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9219 MSFT_GuidEntry
*entry
;
9221 int hash_key
, *guidhashtab
;
9223 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9224 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9226 entry
= file
->guid_seg
.data
;
9228 guidhashtab
= file
->guidhash_seg
.data
;
9229 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9230 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9231 entry
->hreftype
= guid
->hreftype
;
9233 hash_key
= hash_guid(&guid
->guid
);
9234 entry
->next_hash
= guidhashtab
[hash_key
];
9235 guidhashtab
[hash_key
] = offs
;
9237 guid
->offset
= offs
;
9238 offs
+= sizeof(MSFT_GuidEntry
);
9245 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9248 VARTYPE arg_type
= V_VT(value
);
9251 DWORD ret
= file
->custdata_seg
.len
;
9253 if(arg_type
== VT_INT
)
9255 if(arg_type
== VT_UINT
)
9259 if(V_VT(value
) != arg_type
) {
9260 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9262 ERR("VariantChangeType failed: %08x\n", hres
);
9267 /* Check if default value can be stored in-place */
9272 if(V_UI4(&v
) > 0x3ffffff)
9285 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9288 /* have to allocate space in custdata_seg */
9297 /* Construct the data to be allocated */
9300 if(file
->custdata_seg
.data
){
9301 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9302 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9303 file
->custdata_seg
.len
+= sizeof(int) * 2;
9305 file
->custdata_seg
.len
= sizeof(int) * 2;
9306 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9309 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9310 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9312 /* TODO: Check if the encoded data is already present in custdata_seg */
9318 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9321 if(file
->custdata_seg
.data
){
9322 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9323 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9324 file
->custdata_seg
.len
+= len
;
9326 file
->custdata_seg
.len
= len
;
9327 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9330 *((unsigned short *)data
) = V_VT(value
);
9331 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9332 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9333 if(V_BSTR(&v
)[i
] <= 0x7f)
9334 data
[i
+6] = V_BSTR(&v
)[i
];
9338 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9339 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9342 /* TODO: Check if the encoded data is already present in custdata_seg */
9347 FIXME("Argument type not yet handled\n");
9352 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9354 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9356 DWORD offs
= file
->arraydesc_seg
.len
;
9360 /* TODO: we should check for duplicates, but that's harder because each
9361 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9362 * at the library-level) */
9364 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9365 if(!file
->arraydesc_seg
.data
)
9366 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9368 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9369 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9371 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9372 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9373 for(i
= 0; i
< desc
->cDims
; ++i
){
9374 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9375 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9381 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9387 VARTYPE vt
, subtype
;
9398 vt
= desc
->vt
& VT_TYPEMASK
;
9400 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9402 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9403 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9405 *out_size
+= 2 * sizeof(DWORD
);
9406 }else if(vt
== VT_CARRAY
){
9407 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9408 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9410 }else if(vt
== VT_USERDEFINED
){
9411 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9412 encoded
[1] = desc
->u
.hreftype
;
9413 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9415 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9433 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9436 data
= file
->typdesc_seg
.data
;
9437 while(offs
< file
->typdesc_seg
.len
){
9438 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9440 offs
+= sizeof(encoded
);
9443 file
->typdesc_seg
.len
+= sizeof(encoded
);
9444 if(!file
->typdesc_seg
.data
)
9445 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9447 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9449 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9454 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9456 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9457 DWORD ret
= cdguids_seg
->len
, offs
;
9458 MSFT_CDGuid
*cdguid
;
9461 if(list_empty(custdata_list
))
9464 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9465 if(!cdguids_seg
->data
){
9466 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9468 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9469 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9472 offs
= ret
+ sizeof(MSFT_CDGuid
);
9473 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9474 cdguid
->GuidOffset
= cd
->guid
->offset
;
9475 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9476 cdguid
->next
= offs
;
9477 offs
+= sizeof(MSFT_CDGuid
);
9487 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9488 WMSFT_TLBFile
*file
)
9490 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9491 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9492 MSFT_VarRecord
*varrecord
;
9493 MSFT_FuncRecord
*funcrecord
;
9495 DWORD
*name
, *offsets
, offs
;
9497 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9498 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9500 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9502 /* optional fields */
9503 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9504 if(!list_empty(&desc
->custdata_list
))
9505 recorded_size
+= 7 * sizeof(INT
);
9506 else if(desc
->HelpStringContext
!= 0)
9507 recorded_size
+= 6 * sizeof(INT
);
9509 else if(desc
->Entry
)
9510 recorded_size
+= 3 * sizeof(INT
);
9511 else if(desc
->HelpString
)
9512 recorded_size
+= 2 * sizeof(INT
);
9513 else if(desc
->helpcontext
)
9514 recorded_size
+= sizeof(INT
);
9516 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9518 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9519 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9520 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9525 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9528 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9529 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9531 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9533 /* optional fields */
9534 if(desc
->HelpStringContext
!= 0)
9535 recorded_size
+= 5 * sizeof(INT
);
9536 else if(!list_empty(&desc
->custdata_list
))
9537 recorded_size
+= 4 * sizeof(INT
);
9539 else if(desc
->HelpString
)
9540 recorded_size
+= 2 * sizeof(INT
);
9541 else if(desc
->HelpContext
!= 0)
9542 recorded_size
+= sizeof(INT
);
9544 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9547 if(!recorded_size
&& !extra_size
)
9550 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9552 aux_seg
->len
+= recorded_size
+ extra_size
;
9554 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9557 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9559 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9561 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9563 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9566 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9567 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9568 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9569 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9571 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9572 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9573 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9574 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9577 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9582 * ^has_param_defaults
9583 * ^oEntry_is_intresource
9585 funcrecord
->FKCCIC
=
9586 desc
->funcdesc
.funckind
|
9587 (desc
->funcdesc
.invkind
<< 3) |
9588 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9589 (desc
->funcdesc
.callconv
<< 8);
9591 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9592 funcrecord
->FKCCIC
|= 0x2000;
9594 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9595 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9596 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9597 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9600 if(paramdefault_size
> 0)
9601 funcrecord
->FKCCIC
|= 0x1000;
9603 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9604 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9606 /* optional fields */
9608 if(!list_empty(&desc
->custdata_list
)){
9609 size
+= 7 * sizeof(INT
);
9610 funcrecord
->HelpContext
= desc
->helpcontext
;
9611 if(desc
->HelpString
)
9612 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9614 funcrecord
->oHelpString
= -1;
9616 funcrecord
->oEntry
= -1;
9617 else if(IS_INTRESOURCE(desc
->Entry
))
9618 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9620 funcrecord
->oEntry
= desc
->Entry
->offset
;
9621 funcrecord
->res9
= -1;
9622 funcrecord
->resA
= -1;
9623 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9624 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9625 }else if(desc
->HelpStringContext
!= 0){
9626 size
+= 6 * sizeof(INT
);
9627 funcrecord
->HelpContext
= desc
->helpcontext
;
9628 if(desc
->HelpString
)
9629 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9631 funcrecord
->oHelpString
= -1;
9633 funcrecord
->oEntry
= -1;
9634 else if(IS_INTRESOURCE(desc
->Entry
))
9635 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9637 funcrecord
->oEntry
= desc
->Entry
->offset
;
9638 funcrecord
->res9
= -1;
9639 funcrecord
->resA
= -1;
9640 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9641 }else if(desc
->Entry
){
9642 size
+= 3 * sizeof(INT
);
9643 funcrecord
->HelpContext
= desc
->helpcontext
;
9644 if(desc
->HelpString
)
9645 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9647 funcrecord
->oHelpString
= -1;
9649 funcrecord
->oEntry
= -1;
9650 else if(IS_INTRESOURCE(desc
->Entry
))
9651 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9653 funcrecord
->oEntry
= desc
->Entry
->offset
;
9654 }else if(desc
->HelpString
){
9655 size
+= 2 * sizeof(INT
);
9656 funcrecord
->HelpContext
= desc
->helpcontext
;
9657 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9658 }else if(desc
->helpcontext
){
9659 size
+= sizeof(INT
);
9660 funcrecord
->HelpContext
= desc
->helpcontext
;
9663 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9664 size
+= paramdefault_size
;
9666 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9667 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9669 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9670 if(desc
->pParamDesc
[j
].Name
)
9671 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9674 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9676 if(paramdefault_size
){
9677 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9678 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9679 else if(paramdefault_size
)
9684 size
+= sizeof(MSFT_ParameterInfo
);
9687 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9693 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9696 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9697 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9698 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9699 DWORD size
= 5 * sizeof(INT
);
9701 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9702 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9703 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9704 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9706 if(desc
->vardesc
.varkind
== VAR_CONST
){
9707 varrecord
->vardescsize
+= sizeof(VARIANT
);
9708 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9710 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9713 if(desc
->HelpStringContext
!= 0){
9714 size
+= 5 * sizeof(INT
);
9715 varrecord
->HelpContext
= desc
->HelpContext
;
9716 if(desc
->HelpString
)
9717 varrecord
->HelpString
= desc
->HelpString
->offset
;
9719 varrecord
->HelpString
= -1;
9720 varrecord
->res9
= -1;
9721 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9722 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9723 }else if(!list_empty(&desc
->custdata_list
)){
9724 size
+= 4 * sizeof(INT
);
9725 varrecord
->HelpContext
= desc
->HelpContext
;
9726 if(desc
->HelpString
)
9727 varrecord
->HelpString
= desc
->HelpString
->offset
;
9729 varrecord
->HelpString
= -1;
9730 varrecord
->res9
= -1;
9731 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9732 }else if(desc
->HelpString
){
9733 size
+= 2 * sizeof(INT
);
9734 varrecord
->HelpContext
= desc
->HelpContext
;
9735 if(desc
->HelpString
)
9736 varrecord
->HelpString
= desc
->HelpString
->offset
;
9738 varrecord
->HelpString
= -1;
9739 }else if(desc
->HelpContext
!= 0){
9740 size
+= sizeof(INT
);
9741 varrecord
->HelpContext
= desc
->HelpContext
;
9744 varrecord
->Info
= size
| (i
<< 16);
9750 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9753 memid
= (MEMBERID
*)varrecord
;
9754 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9755 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9756 *memid
= desc
->funcdesc
.memid
;
9759 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9760 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9761 *memid
= desc
->vardesc
.memid
;
9765 name
= (UINT
*)memid
;
9766 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9767 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9769 *name
= desc
->Name
->offset
;
9774 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9775 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9777 *name
= desc
->Name
->offset
;
9786 typedef struct tagWMSFT_RefChunk
{
9793 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9795 DWORD offs
= file
->ref_seg
.len
, i
;
9796 WMSFT_RefChunk
*chunk
;
9798 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9799 if(!file
->ref_seg
.data
)
9800 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9802 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9804 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9806 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9807 chunk
->href
= info
->impltypes
[i
].hRef
;
9808 chunk
->res04
= info
->impltypes
[i
].implflags
;
9810 if(i
< info
->typeattr
.cImplTypes
- 1)
9811 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9820 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9824 size
= sizeof(MSFT_TypeInfoBase
);
9827 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9828 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9829 base
->typekind
= TKIND_DISPATCH
;
9831 base
->typekind
= info
->typeattr
.typekind
;
9832 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9833 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
9834 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9839 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
9845 base
->posguid
= info
->guid
->offset
;
9848 base
->flags
= info
->typeattr
.wTypeFlags
;
9850 base
->NameOffset
= info
->Name
->offset
;
9852 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9853 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9855 base
->NameOffset
= -1;
9857 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
9859 base
->docstringoffs
= info
->DocString
->offset
;
9861 base
->docstringoffs
= -1;
9862 base
->helpstringcontext
= info
->dwHelpStringContext
;
9863 base
->helpcontext
= info
->dwHelpContext
;
9864 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9865 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
9866 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
9867 base
->size
= info
->typeattr
.cbSizeInstance
;
9868 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
9869 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9870 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
9871 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9872 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
9874 base
->datatype1
= info
->DllName
->offset
;
9876 base
->datatype1
= -1;
9878 if(info
->typeattr
.cImplTypes
> 0)
9879 base
->datatype1
= info
->impltypes
[0].hRef
;
9881 base
->datatype1
= -1;
9883 base
->datatype2
= index
; /* FIXME: i think there's more here */
9891 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9895 file
->typeinfo_seg
.len
= 0;
9896 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9897 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9898 *junk
= file
->typeinfo_seg
.len
;
9900 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9903 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9904 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9906 file
->aux_seg
.len
= 0;
9907 file
->aux_seg
.data
= NULL
;
9909 file
->typeinfo_seg
.len
= 0;
9910 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9911 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9912 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9913 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9917 typedef struct tagWMSFT_ImpFile
{
9923 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9926 WMSFT_ImpFile
*impfile
;
9928 DWORD last_offs
= 0;
9930 file
->impfile_seg
.len
= 0;
9931 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9935 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9939 path
= implib
->name
;
9940 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9942 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9945 size
+= sizeof(INT16
);
9947 size
= (size
+ 4) & ~0x3;
9951 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9954 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9956 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9957 int strlen
= 0, size
;
9959 impfile
= (WMSFT_ImpFile
*)data
;
9960 impfile
->guid_offs
= implib
->guid
->offset
;
9961 impfile
->lcid
= implib
->lcid
;
9962 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9964 data
+= sizeof(WMSFT_ImpFile
);
9967 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9971 path
= implib
->name
;
9972 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9973 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9975 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9978 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9980 size
= strlen
+ sizeof(INT16
);
9982 size
= (size
+ 4) & ~0x3;
9985 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9988 implib
->offset
= last_offs
;
9989 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9993 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9996 TLBRefType
*ref_type
;
9999 WMSFT_compile_impfile(This
, file
);
10001 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
10002 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
10004 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
10005 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
10006 if(ref_type
->index
== TLB_REF_USE_GUID
){
10007 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
10008 info
->oGuid
= ref_type
->guid
->offset
;
10010 info
->oGuid
= ref_type
->index
;
10011 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
10017 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10019 file
->guidhash_seg
.len
= 0x80;
10020 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
10021 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
10024 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10026 file
->namehash_seg
.len
= 0x200;
10027 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
10028 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
10031 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
10033 if(contents
&& contents
->len
){
10034 segdir
->offset
= *running_offset
;
10035 segdir
->length
= contents
->len
;
10036 *running_offset
+= segdir
->length
;
10038 segdir
->offset
= -1;
10039 segdir
->length
= 0;
10042 /* TODO: do these ever change? */
10043 segdir
->res08
= -1;
10044 segdir
->res0c
= 0xf;
10047 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10051 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10054 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10058 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10060 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10061 base
->memoffset
+= file_len
;
10068 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10070 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
10071 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
10072 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
10073 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
10074 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
10075 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
10076 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
10077 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
10078 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
10079 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
10080 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
10081 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
10082 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
10083 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
10086 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10088 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10089 WMSFT_TLBFile file
;
10090 DWORD written
, junk_size
, junk_offs
, running_offset
;
10097 TRACE("%p\n", This
);
10099 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10100 if(This
->typeinfos
[i
]->needs_layout
)
10101 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10103 memset(&file
, 0, sizeof(file
));
10105 file
.header
.magic1
= 0x5446534D;
10106 file
.header
.magic2
= 0x00010002;
10107 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10108 file
.header
.lcid2
= This
->set_lcid
;
10109 file
.header
.varflags
= 0x40 | This
->syskind
;
10110 if (This
->HelpFile
)
10111 file
.header
.varflags
|= 0x10;
10112 if (This
->HelpStringDll
)
10113 file
.header
.varflags
|= HELPDLLFLAG
;
10114 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10115 file
.header
.flags
= This
->libflags
;
10116 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10117 file
.header
.helpcontext
= This
->dwHelpContext
;
10118 file
.header
.res44
= 0x20;
10119 file
.header
.res48
= 0x80;
10120 file
.header
.dispatchpos
= This
->dispatch_href
;
10122 WMSFT_compile_namehash(This
, &file
);
10123 /* do name and string compilation to get offsets for other compilations */
10124 hres
= WMSFT_compile_names(This
, &file
);
10126 WMSFT_free_file(&file
);
10130 hres
= WMSFT_compile_strings(This
, &file
);
10132 WMSFT_free_file(&file
);
10136 WMSFT_compile_guidhash(This
, &file
);
10137 hres
= WMSFT_compile_guids(This
, &file
);
10139 WMSFT_free_file(&file
);
10144 file
.header
.helpfile
= This
->HelpFile
->offset
;
10146 file
.header
.helpfile
= -1;
10148 if(This
->DocString
)
10149 file
.header
.helpstring
= This
->DocString
->offset
;
10151 file
.header
.helpstring
= -1;
10153 /* do some more segment compilation */
10154 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10155 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10158 file
.header
.NameOffset
= This
->Name
->offset
;
10160 file
.header
.NameOffset
= -1;
10162 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10165 file
.header
.posguid
= This
->guid
->offset
;
10167 file
.header
.posguid
= -1;
10169 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10170 if(file
.header
.varflags
& HELPDLLFLAG
)
10171 junk_size
+= sizeof(DWORD
);
10173 junk
= heap_alloc_zero(junk_size
);
10174 if(file
.header
.varflags
& HELPDLLFLAG
){
10175 *junk
= This
->HelpStringDll
->offset
;
10184 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10185 WMSFT_compile_impinfo(This
, &file
);
10187 running_offset
= 0;
10189 TRACE("header at: 0x%x\n", running_offset
);
10190 running_offset
+= sizeof(file
.header
);
10192 TRACE("junk at: 0x%x\n", running_offset
);
10193 running_offset
+= junk_size
;
10195 TRACE("segdir at: 0x%x\n", running_offset
);
10196 running_offset
+= sizeof(file
.segdir
);
10198 TRACE("typeinfo at: 0x%x\n", running_offset
);
10199 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10201 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10202 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10204 TRACE("guidtab at: 0x%x\n", running_offset
);
10205 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10207 TRACE("reftab at: 0x%x\n", running_offset
);
10208 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10210 TRACE("impinfo at: 0x%x\n", running_offset
);
10211 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10213 TRACE("impfiles at: 0x%x\n", running_offset
);
10214 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10216 TRACE("namehashtab at: 0x%x\n", running_offset
);
10217 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10219 TRACE("nametab at: 0x%x\n", running_offset
);
10220 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10222 TRACE("stringtab at: 0x%x\n", running_offset
);
10223 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10225 TRACE("typdesc at: 0x%x\n", running_offset
);
10226 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10228 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10229 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10231 TRACE("custdata at: 0x%x\n", running_offset
);
10232 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10234 TRACE("cdguids at: 0x%x\n", running_offset
);
10235 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10237 TRACE("res0e at: 0x%x\n", running_offset
);
10238 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10240 TRACE("res0f at: 0x%x\n", running_offset
);
10241 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10243 TRACE("aux_seg at: 0x%x\n", running_offset
);
10245 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10247 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10248 FILE_ATTRIBUTE_NORMAL
, 0);
10249 if (outfile
== INVALID_HANDLE_VALUE
){
10250 WMSFT_free_file(&file
);
10252 return TYPE_E_IOERROR
;
10255 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10257 WMSFT_free_file(&file
);
10258 CloseHandle(outfile
);
10260 return TYPE_E_IOERROR
;
10263 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10266 WMSFT_free_file(&file
);
10267 CloseHandle(outfile
);
10268 return TYPE_E_IOERROR
;
10271 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10273 WMSFT_free_file(&file
);
10274 CloseHandle(outfile
);
10275 return TYPE_E_IOERROR
;
10278 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10279 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10280 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10281 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10282 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10283 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10284 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10285 WMSFT_write_segment(outfile
, &file
.name_seg
);
10286 WMSFT_write_segment(outfile
, &file
.string_seg
);
10287 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10288 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10289 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10290 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10291 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10293 WMSFT_free_file(&file
);
10295 CloseHandle(outfile
);
10300 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10303 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10304 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10308 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10309 REFGUID guid
, VARIANT
*varVal
)
10311 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10314 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10316 if (!guid
|| !varVal
)
10317 return E_INVALIDARG
;
10319 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10321 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10324 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10325 ULONG helpStringContext
)
10327 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10328 FIXME("%p %u - stub\n", This
, helpStringContext
);
10332 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10335 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10336 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10339 return E_INVALIDARG
;
10341 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10346 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10347 ICreateTypeLib2_fnQueryInterface
,
10348 ICreateTypeLib2_fnAddRef
,
10349 ICreateTypeLib2_fnRelease
,
10350 ICreateTypeLib2_fnCreateTypeInfo
,
10351 ICreateTypeLib2_fnSetName
,
10352 ICreateTypeLib2_fnSetVersion
,
10353 ICreateTypeLib2_fnSetGuid
,
10354 ICreateTypeLib2_fnSetDocString
,
10355 ICreateTypeLib2_fnSetHelpFileName
,
10356 ICreateTypeLib2_fnSetHelpContext
,
10357 ICreateTypeLib2_fnSetLcid
,
10358 ICreateTypeLib2_fnSetLibFlags
,
10359 ICreateTypeLib2_fnSaveAllChanges
,
10360 ICreateTypeLib2_fnDeleteTypeInfo
,
10361 ICreateTypeLib2_fnSetCustData
,
10362 ICreateTypeLib2_fnSetHelpStringContext
,
10363 ICreateTypeLib2_fnSetHelpStringDll
10366 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10367 REFIID riid
, void **object
)
10369 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10371 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10374 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10376 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10378 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10381 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10383 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10385 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10388 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10391 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10393 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10395 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10400 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10403 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10407 TRACE("%p %x\n", This
, typeFlags
);
10409 if (typeFlags
& TYPEFLAG_FDUAL
) {
10410 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10412 ITypeInfo
*dispatch
;
10416 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10420 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10421 ITypeLib_Release(stdole
);
10425 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10426 ITypeInfo_Release(dispatch
);
10431 old_flags
= This
->typeattr
.wTypeFlags
;
10432 This
->typeattr
.wTypeFlags
= typeFlags
;
10434 hres
= ICreateTypeInfo2_LayOut(iface
);
10435 if (FAILED(hres
)) {
10436 This
->typeattr
.wTypeFlags
= old_flags
;
10443 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10446 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10448 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10451 return E_INVALIDARG
;
10453 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10458 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10461 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10463 TRACE("%p %d\n", This
, helpContext
);
10465 This
->dwHelpContext
= helpContext
;
10470 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10471 WORD majorVerNum
, WORD minorVerNum
)
10473 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10475 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10477 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10478 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10483 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10484 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10486 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10488 ITypeLib
*container
;
10489 TLBRefType
*ref_type
;
10491 TYPEATTR
*typeattr
;
10495 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10497 if (!typeInfo
|| !refType
)
10498 return E_INVALIDARG
;
10500 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10504 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10505 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10507 ITypeLib_Release(container
);
10509 *refType
= target
->hreftype
;
10514 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10515 if (FAILED(hres
)) {
10516 ITypeLib_Release(container
);
10520 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10521 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10522 implib
->lcid
== libattr
->lcid
&&
10523 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10524 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10528 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10529 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10531 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10532 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10533 implib
->name
= SysAllocString(our_container
->path
);
10535 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10536 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10538 implib
->name
= NULL
;
10539 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10543 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10544 implib
->lcid
= libattr
->lcid
;
10545 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10546 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10548 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10551 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10552 ITypeLib_Release(container
);
10554 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10559 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10560 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10561 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10562 ref_type
->tkind
== typeattr
->typekind
)
10567 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10568 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10570 ref_type
->tkind
= typeattr
->typekind
;
10571 ref_type
->pImpTLInfo
= implib
;
10572 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10574 ref_type
->index
= TLB_REF_USE_GUID
;
10576 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10578 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10581 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10583 *refType
= ref_type
->reference
| 0x1;
10585 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10586 This
->pTypeLib
->dispatch_href
= *refType
;
10591 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10592 UINT index
, FUNCDESC
*funcDesc
)
10594 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10595 TLBFuncDesc tmp_func_desc
, *func_desc
;
10600 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10602 if (!funcDesc
|| funcDesc
->oVft
& 3)
10603 return E_INVALIDARG
;
10605 switch (This
->typeattr
.typekind
) {
10607 if (funcDesc
->funckind
!= FUNC_STATIC
)
10608 return TYPE_E_BADMODULEKIND
;
10610 case TKIND_DISPATCH
:
10611 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10612 return TYPE_E_BADMODULEKIND
;
10615 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10616 return TYPE_E_BADMODULEKIND
;
10619 if (index
> This
->typeattr
.cFuncs
)
10620 return TYPE_E_ELEMENTNOTFOUND
;
10622 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10623 !funcDesc
->cParams
)
10624 return TYPE_E_INCONSISTENTPROPFUNCS
;
10627 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10628 funcDesc
->oVft
% 8 != 0)
10629 return E_INVALIDARG
;
10632 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10633 TLBFuncDesc_Constructor(&tmp_func_desc
);
10635 tmp_func_desc
.funcdesc
= *funcDesc
;
10637 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10638 tmp_func_desc
.funcdesc
.oVft
|= 1;
10640 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10641 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10642 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10644 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10645 tmp_func_desc
.funcdesc
.cScodes
= 0;
10648 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10649 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10650 buf_size
+= sizeof(ELEMDESC
);
10651 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10653 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10654 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10656 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10657 if (FAILED(hres
)) {
10658 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10659 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10663 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10664 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10665 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10666 if (FAILED(hres
)) {
10667 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10668 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10671 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10672 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10673 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10674 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10675 if (FAILED(hres
)) {
10676 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10677 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10683 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10685 if (This
->funcdescs
) {
10686 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10687 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10689 if (index
< This
->typeattr
.cFuncs
) {
10690 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10691 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10692 func_desc
= This
->funcdescs
+ index
;
10694 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10696 /* move custdata lists to the new memory location */
10697 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10699 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10700 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10701 list_init(&fd
->custdata_list
);
10703 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10704 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10709 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10711 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10712 list_init(&func_desc
->custdata_list
);
10714 ++This
->typeattr
.cFuncs
;
10716 This
->needs_layout
= TRUE
;
10721 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10722 UINT index
, HREFTYPE refType
)
10724 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10725 TLBImplType
*impl_type
;
10728 TRACE("%p %u %d\n", This
, index
, refType
);
10730 switch(This
->typeattr
.typekind
){
10731 case TKIND_COCLASS
: {
10733 FIXME("Unhandled index: -1\n");
10737 if(index
!= This
->typeattr
.cImplTypes
)
10738 return TYPE_E_ELEMENTNOTFOUND
;
10742 case TKIND_INTERFACE
:
10743 case TKIND_DISPATCH
:
10744 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10745 return TYPE_E_ELEMENTNOTFOUND
;
10748 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10752 if (This
->impltypes
){
10755 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10756 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10758 if (index
< This
->typeattr
.cImplTypes
) {
10759 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10760 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10761 impl_type
= This
->impltypes
+ index
;
10763 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10765 /* move custdata lists to the new memory location */
10766 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10768 TLBImplType
*it
= &This
->impltypes
[i
];
10769 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10770 list_init(&it
->custdata_list
);
10772 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10773 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10778 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10780 memset(impl_type
, 0, sizeof(TLBImplType
));
10781 TLBImplType_Constructor(impl_type
);
10782 impl_type
->hRef
= refType
;
10784 ++This
->typeattr
.cImplTypes
;
10786 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10787 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10789 hres
= ICreateTypeInfo2_LayOut(iface
);
10796 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10797 UINT index
, INT implTypeFlags
)
10799 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10800 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10802 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10804 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10805 return TYPE_E_BADMODULEKIND
;
10807 if (index
>= This
->typeattr
.cImplTypes
)
10808 return TYPE_E_ELEMENTNOTFOUND
;
10810 impl_type
->implflags
= implTypeFlags
;
10815 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10818 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10820 TRACE("%p %d\n", This
, alignment
);
10822 This
->typeattr
.cbAlignment
= alignment
;
10827 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10830 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10832 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10835 return E_INVALIDARG
;
10837 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10839 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10844 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10845 UINT index
, VARDESC
*varDesc
)
10847 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10848 TLBVarDesc
*var_desc
;
10850 TRACE("%p %u %p\n", This
, index
, varDesc
);
10852 if (This
->vardescs
){
10855 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10856 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
10858 if (index
< This
->typeattr
.cVars
) {
10859 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10860 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
10861 var_desc
= This
->vardescs
+ index
;
10863 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
10865 /* move custdata lists to the new memory location */
10866 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
10868 TLBVarDesc
*var
= &This
->vardescs
[i
];
10869 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10870 list_init(&var
->custdata_list
);
10872 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10873 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10878 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10880 TLBVarDesc_Constructor(var_desc
);
10881 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10882 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10884 ++This
->typeattr
.cVars
;
10886 This
->needs_layout
= TRUE
;
10891 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10892 UINT index
, LPOLESTR
*names
, UINT numNames
)
10894 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10895 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10898 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10901 return E_INVALIDARG
;
10903 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
10904 return TYPE_E_ELEMENTNOTFOUND
;
10906 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10907 if(numNames
> func_desc
->funcdesc
.cParams
)
10908 return TYPE_E_ELEMENTNOTFOUND
;
10910 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10911 return TYPE_E_ELEMENTNOTFOUND
;
10913 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
10914 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10915 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10916 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10917 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10918 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10920 return TYPE_E_AMBIGUOUSNAME
;
10924 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10926 for (i
= 1; i
< numNames
; ++i
) {
10927 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10928 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10934 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10935 UINT index
, LPOLESTR name
)
10937 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10939 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10942 return E_INVALIDARG
;
10944 if(index
>= This
->typeattr
.cVars
)
10945 return TYPE_E_ELEMENTNOTFOUND
;
10947 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10951 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10952 TYPEDESC
*tdescAlias
)
10954 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10957 TRACE("%p %p\n", This
, tdescAlias
);
10960 return E_INVALIDARG
;
10962 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
10963 return TYPE_E_BADMODULEKIND
;
10965 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
10969 heap_free(This
->tdescAlias
);
10970 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10971 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10976 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10977 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10979 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10980 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10984 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10985 UINT index
, LPOLESTR docString
)
10987 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10988 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10990 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10993 return E_INVALIDARG
;
10995 if(index
>= This
->typeattr
.cFuncs
)
10996 return TYPE_E_ELEMENTNOTFOUND
;
10998 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11003 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
11004 UINT index
, LPOLESTR docString
)
11006 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11007 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11009 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11012 return E_INVALIDARG
;
11014 if(index
>= This
->typeattr
.cVars
)
11015 return TYPE_E_ELEMENTNOTFOUND
;
11017 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11022 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
11023 UINT index
, DWORD helpContext
)
11025 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11026 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11028 TRACE("%p %u %d\n", This
, index
, helpContext
);
11030 if(index
>= This
->typeattr
.cFuncs
)
11031 return TYPE_E_ELEMENTNOTFOUND
;
11033 func_desc
->helpcontext
= helpContext
;
11038 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
11039 UINT index
, DWORD helpContext
)
11041 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11042 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11044 TRACE("%p %u %d\n", This
, index
, helpContext
);
11046 if(index
>= This
->typeattr
.cVars
)
11047 return TYPE_E_ELEMENTNOTFOUND
;
11049 var_desc
->HelpContext
= helpContext
;
11054 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
11055 UINT index
, BSTR bstrMops
)
11057 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11058 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
11062 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
11065 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11067 TRACE("%p %p\n", This
, idlDesc
);
11070 return E_INVALIDARG
;
11072 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11073 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11078 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11080 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11082 TLBFuncDesc
*func_desc
;
11083 UINT user_vft
= 0, i
, depth
= 0;
11084 HRESULT hres
= S_OK
;
11086 TRACE("%p\n", This
);
11088 This
->needs_layout
= FALSE
;
11090 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
11094 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11099 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11101 if (SUCCEEDED(hres
)) {
11102 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11104 if (SUCCEEDED(hres
)) {
11105 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11106 if (FAILED(hres
)) {
11107 ITypeInfo_Release(inh
);
11108 ITypeInfo_Release(tinfo
);
11111 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11112 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11116 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11117 if(SUCCEEDED(hres
)){
11119 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11120 if(SUCCEEDED(hres
)){
11121 ITypeInfo_Release(inh
);
11125 }while(SUCCEEDED(hres
));
11128 ITypeInfo_Release(inh
);
11129 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11130 This
->typeattr
.cbSizeVft
= 0;
11133 ITypeInfo_Release(tinfo
);
11136 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11137 This
->typeattr
.cbSizeVft
= 0;
11140 ITypeInfo_Release(tinfo
);
11143 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11144 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11146 This
->typeattr
.cbSizeVft
= 0;
11148 func_desc
= This
->funcdescs
;
11150 while (i
< This
->typeattr
.cFuncs
) {
11151 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11152 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11154 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11155 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11157 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11159 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11162 BOOL reset
= FALSE
;
11164 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11166 iter
= This
->funcdescs
;
11167 while (j
< This
->typeattr
.cFuncs
) {
11168 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11170 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11173 ++func_desc
->funcdesc
.memid
;
11174 iter
= This
->funcdescs
;
11187 if (user_vft
> This
->typeattr
.cbSizeVft
)
11188 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11190 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11191 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11192 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11194 BOOL reset
= FALSE
;
11197 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11199 iter
= This
->vardescs
;
11200 while (j
< This
->typeattr
.cVars
) {
11201 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11203 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11206 ++var_desc
->vardesc
.memid
;
11207 iter
= This
->vardescs
;
11217 ITypeInfo_Release(tinfo
);
11221 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11224 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11225 FIXME("%p %u - stub\n", This
, index
);
11229 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11230 MEMBERID memid
, INVOKEKIND invKind
)
11232 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11233 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11237 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11240 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11241 FIXME("%p %u - stub\n", This
, index
);
11245 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11248 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11249 FIXME("%p %x - stub\n", This
, memid
);
11253 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11256 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11257 FIXME("%p %u - stub\n", This
, index
);
11261 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11262 REFGUID guid
, VARIANT
*varVal
)
11266 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11268 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11270 if (!guid
|| !varVal
)
11271 return E_INVALIDARG
;
11273 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11275 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11278 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11279 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11281 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11282 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11286 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11287 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11289 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11290 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11294 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11295 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11297 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11298 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11302 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11303 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11305 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11306 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11310 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11311 ULONG helpStringContext
)
11313 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11315 TRACE("%p %u\n", This
, helpStringContext
);
11317 This
->dwHelpStringContext
= helpStringContext
;
11322 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11323 UINT index
, ULONG helpStringContext
)
11325 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11326 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11330 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11331 UINT index
, ULONG helpStringContext
)
11333 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11334 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11338 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11340 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11341 FIXME("%p - stub\n", This
);
11345 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11348 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11350 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11353 return E_INVALIDARG
;
11355 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11360 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11361 ICreateTypeInfo2_fnQueryInterface
,
11362 ICreateTypeInfo2_fnAddRef
,
11363 ICreateTypeInfo2_fnRelease
,
11364 ICreateTypeInfo2_fnSetGuid
,
11365 ICreateTypeInfo2_fnSetTypeFlags
,
11366 ICreateTypeInfo2_fnSetDocString
,
11367 ICreateTypeInfo2_fnSetHelpContext
,
11368 ICreateTypeInfo2_fnSetVersion
,
11369 ICreateTypeInfo2_fnAddRefTypeInfo
,
11370 ICreateTypeInfo2_fnAddFuncDesc
,
11371 ICreateTypeInfo2_fnAddImplType
,
11372 ICreateTypeInfo2_fnSetImplTypeFlags
,
11373 ICreateTypeInfo2_fnSetAlignment
,
11374 ICreateTypeInfo2_fnSetSchema
,
11375 ICreateTypeInfo2_fnAddVarDesc
,
11376 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11377 ICreateTypeInfo2_fnSetVarName
,
11378 ICreateTypeInfo2_fnSetTypeDescAlias
,
11379 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11380 ICreateTypeInfo2_fnSetFuncDocString
,
11381 ICreateTypeInfo2_fnSetVarDocString
,
11382 ICreateTypeInfo2_fnSetFuncHelpContext
,
11383 ICreateTypeInfo2_fnSetVarHelpContext
,
11384 ICreateTypeInfo2_fnSetMops
,
11385 ICreateTypeInfo2_fnSetTypeIdldesc
,
11386 ICreateTypeInfo2_fnLayOut
,
11387 ICreateTypeInfo2_fnDeleteFuncDesc
,
11388 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11389 ICreateTypeInfo2_fnDeleteVarDesc
,
11390 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11391 ICreateTypeInfo2_fnDeleteImplType
,
11392 ICreateTypeInfo2_fnSetCustData
,
11393 ICreateTypeInfo2_fnSetFuncCustData
,
11394 ICreateTypeInfo2_fnSetParamCustData
,
11395 ICreateTypeInfo2_fnSetVarCustData
,
11396 ICreateTypeInfo2_fnSetImplTypeCustData
,
11397 ICreateTypeInfo2_fnSetHelpStringContext
,
11398 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11399 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11400 ICreateTypeInfo2_fnInvalidate
,
11401 ICreateTypeInfo2_fnSetName
11404 /******************************************************************************
11405 * ClearCustData (OLEAUT32.171)
11407 * Clear a custom data type's data.
11410 * lpCust [I] The custom data type instance
11415 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11417 if (lpCust
&& lpCust
->cCustData
)
11419 if (lpCust
->prgCustData
)
11423 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11424 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11426 CoTaskMemFree(lpCust
->prgCustData
);
11427 lpCust
->prgCustData
= NULL
;
11429 lpCust
->cCustData
= 0;