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"
76 #include "wine/heap.h"
77 #include "wine/list.h"
79 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
80 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
94 WORD type_id
; /* Type identifier */
95 WORD count
; /* Number of resources of this type */
96 DWORD resloader
; /* SetResourceHandler() */
102 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
103 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
104 static void TLB_FreeVarDesc(VARDESC
*);
106 /****************************************************************************
109 * Takes p_iVal (which is in little endian) and returns it
110 * in the host machine's byte order.
112 #ifdef WORDS_BIGENDIAN
113 static WORD
FromLEWord(WORD p_iVal
)
115 return (((p_iVal
& 0x00FF) << 8) |
116 ((p_iVal
& 0xFF00) >> 8));
120 static DWORD
FromLEDWord(DWORD p_iVal
)
122 return (((p_iVal
& 0x000000FF) << 24) |
123 ((p_iVal
& 0x0000FF00) << 8) |
124 ((p_iVal
& 0x00FF0000) >> 8) |
125 ((p_iVal
& 0xFF000000) >> 24));
128 #define FromLEWord(X) (X)
129 #define FromLEDWord(X) (X)
132 #define DISPATCH_HREF_OFFSET 0x01000000
133 #define DISPATCH_HREF_MASK 0xff000000
135 /****************************************************************************
138 * Fix byte order in any structure if necessary
140 #ifdef WORDS_BIGENDIAN
141 static void FromLEWords(void *p_Val
, int p_iSize
)
145 p_iSize
/= sizeof(WORD
);
148 *Val
= FromLEWord(*Val
);
155 static void FromLEDWords(void *p_Val
, int p_iSize
)
159 p_iSize
/= sizeof(DWORD
);
162 *Val
= FromLEDWord(*Val
);
168 #define FromLEWords(X,Y) /*nothing*/
169 #define FromLEDWords(X,Y) /*nothing*/
173 * Find a typelib key which matches a requested maj.min version.
175 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
177 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
181 INT best_maj
= -1, best_min
= -1;
184 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
185 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
187 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
190 len
= sizeof(key_name
);
192 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
196 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
198 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
200 if (*wMaj
== 0xffff && *wMin
== 0xffff)
202 if (v_maj
> best_maj
) best_maj
= v_maj
;
203 if (v_min
> best_min
) best_min
= v_min
;
205 else if (*wMaj
== v_maj
)
212 break; /* exact match */
214 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
217 len
= sizeof(key_name
);
221 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
223 if (*wMaj
== 0xffff && *wMin
== 0xffff)
225 if (best_maj
>= 0 && best_min
>= 0)
233 if (*wMaj
== best_maj
&& best_min
>= 0)
241 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
242 /* buffer must be at least 60 characters long */
243 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
245 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
246 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
248 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
249 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
250 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
254 /* get the path of an interface key, in the form "Interface\\<guid>" */
255 /* buffer must be at least 50 characters long */
256 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
258 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
260 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
261 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
265 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
266 /* buffer must be at least 16 characters long */
267 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
269 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
270 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
271 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
272 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
274 sprintfW( buffer
, LcidFormatW
, lcid
);
277 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
278 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
279 case SYS_WIN64
: strcatW( buffer
, win64W
); break;
281 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
287 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
289 struct tlibredirect_data
303 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
304 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
305 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
307 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
311 WCHAR Path
[MAX_PATH
];
314 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
318 ACTCTX_SECTION_KEYED_DATA data
;
320 data
.cbSize
= sizeof(data
);
321 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
323 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
327 if ((wMaj
!= 0xffff || wMin
!= 0xffff) && (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
))
328 return TYPE_E_LIBNOTREGISTERED
;
330 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
331 len
= SearchPathW( NULL
, nameW
, NULL
, ARRAY_SIZE( Path
), Path
, NULL
);
332 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
334 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
335 *path
= SysAllocString( Path
);
340 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
341 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
343 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
344 if (res
== ERROR_FILE_NOT_FOUND
)
346 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
347 return TYPE_E_LIBNOTREGISTERED
;
349 else if (res
!= ERROR_SUCCESS
)
351 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
352 return TYPE_E_REGISTRYACCESS
;
357 LONG dwPathLen
= sizeof(Path
);
359 get_lcid_subkey( myLCID
, syskind
, buffer
);
361 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
365 else if (myLCID
== lcid
)
367 /* try with sub-langid */
368 myLCID
= SUBLANGID(lcid
);
370 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
372 /* try with system langid */
382 *path
= SysAllocString( Path
);
387 TRACE_(typelib
)("-- 0x%08x\n", hr
);
391 /****************************************************************************
392 * QueryPathOfRegTypeLib [OLEAUT32.164]
394 * Gets the path to a registered type library.
397 * guid [I] referenced guid
398 * wMaj [I] major version
399 * wMin [I] minor version
401 * path [O] path of typelib
405 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
406 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
409 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
413 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
418 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
421 /******************************************************************************
422 * CreateTypeLib [OLEAUT32.160] creates a typelib
428 HRESULT WINAPI
CreateTypeLib(
429 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
431 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
435 /******************************************************************************
436 * LoadTypeLib [OLEAUT32.161]
438 * Loads a type library
441 * szFile [I] Name of file to load from.
442 * pptLib [O] Pointer that receives ITypeLib object on success.
449 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
451 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
453 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
454 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
457 /******************************************************************************
458 * LoadTypeLibEx [OLEAUT32.183]
460 * Loads and optionally registers a type library
466 HRESULT WINAPI
LoadTypeLibEx(
467 LPCOLESTR szFile
, /* [in] Name of file to load from */
468 REGKIND regkind
, /* [in] Specify kind of registration */
469 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
471 WCHAR szPath
[MAX_PATH
+1];
474 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
476 if (!szFile
|| !pptLib
)
481 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
486 case REGKIND_DEFAULT
:
487 /* don't register typelibs supplied with full path. Experimentation confirms the following */
488 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
489 (szFile
[0] && (szFile
[1] == ':'))) break;
490 /* else fall-through */
492 case REGKIND_REGISTER
:
493 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
495 ITypeLib_Release(*pptLib
);
503 TRACE(" returns %08x\n",res
);
507 /******************************************************************************
508 * LoadRegTypeLib [OLEAUT32.162]
510 * Loads a registered type library.
513 * rguid [I] GUID of the registered type library.
514 * wVerMajor [I] major version.
515 * wVerMinor [I] minor version.
516 * lcid [I] locale ID.
517 * ppTLib [O] pointer that receives an ITypeLib object on success.
521 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
524 HRESULT WINAPI
LoadRegTypeLib(
536 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
540 res
= LoadTypeLib(bstr
, ppTLib
);
543 if ((wVerMajor
!=0xffff || wVerMinor
!=0xffff) && *ppTLib
)
547 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
550 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
551 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
555 ITypeLib_Release(*ppTLib
);
557 res
= TYPE_E_LIBNOTREGISTERED
;
563 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
569 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
570 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
571 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
572 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
573 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
574 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
576 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
581 static const WCHAR typelib_proxy_clsid
[] = {'{','0','0','0','2','0','4','2','4','-',
582 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
583 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
584 static const WCHAR dispatch_proxy_clsid
[] = {'{','0','0','0','2','0','4','2','0','-',
585 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
586 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
588 get_interface_key( &tattr
->guid
, keyName
);
589 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
590 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
592 const WCHAR
*proxy_clsid
;
594 if (tattr
->typekind
== TKIND_INTERFACE
|| (tattr
->wTypeFlags
& TYPEFLAG_FDUAL
))
595 proxy_clsid
= typelib_proxy_clsid
;
597 proxy_clsid
= dispatch_proxy_clsid
;
600 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
601 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
603 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
604 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
605 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
606 (const BYTE
*)proxy_clsid
, sizeof(typelib_proxy_clsid
));
610 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
611 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
612 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
613 (const BYTE
*)proxy_clsid
, sizeof(typelib_proxy_clsid
));
617 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
618 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
621 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
622 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
624 StringFromGUID2(&libattr
->guid
, buffer
, 40);
625 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
626 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
627 sprintfW(buffer
, fmtver
, libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
628 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
629 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
637 /******************************************************************************
638 * RegisterTypeLib [OLEAUT32.163]
639 * Adds information about a type library to the System Registry
641 * Docs: ITypeLib FAR * ptlib
642 * Docs: OLECHAR FAR* szFullPath
643 * Docs: OLECHAR FAR* szHelpDir
649 HRESULT WINAPI
RegisterTypeLib(
650 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
651 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
652 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
664 if (ptlib
== NULL
|| szFullPath
== NULL
)
667 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
671 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
674 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
677 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
678 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
682 /* Set the human-readable name of the typelib */
683 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
687 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
688 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
694 /* Make up the name of the typelib path subkey */
695 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
697 /* Create the typelib path subkey */
698 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
699 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
701 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
702 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
710 /* Create the flags subkey */
711 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
712 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
714 /* FIXME: is %u correct? */
715 static const WCHAR formatW
[] = {'%','u',0};
717 sprintfW(buf
, formatW
, attr
->wLibFlags
);
718 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
719 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
727 /* create the helpdir subkey */
728 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
729 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
731 BOOL freeHelpDir
= FALSE
;
734 /* if we created a new key, and helpDir was null, set the helpdir
735 to the directory which contains the typelib. However,
736 if we just opened an existing key, we leave the helpdir alone */
737 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
738 szHelpDir
= SysAllocString(szFullPath
);
739 pIndexStr
= strrchrW(szHelpDir
, '\\');
746 /* if we have an szHelpDir, set it! */
747 if (szHelpDir
!= NULL
) {
748 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
749 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
755 if (freeHelpDir
) SysFreeString(szHelpDir
);
767 /* register OLE Automation-compatible interfaces for this typelib */
768 types
= ITypeLib_GetTypeInfoCount(ptlib
);
769 for (tidx
=0; tidx
<types
; tidx
++) {
770 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
771 LPOLESTR name
= NULL
;
772 ITypeInfo
*tinfo
= NULL
;
774 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
777 case TKIND_INTERFACE
:
778 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
779 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
783 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
784 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
788 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
793 TYPEATTR
*tattr
= NULL
;
794 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
797 TRACE_(typelib
)("guid=%s, flags=%04x (",
798 debugstr_guid(&tattr
->guid
),
801 if (TRACE_ON(typelib
)) {
802 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
822 /* Register all dispinterfaces (which includes dual interfaces) and
823 oleautomation interfaces */
824 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
825 kind
== TKIND_DISPATCH
)
828 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
830 /* register interface<->typelib coupling */
831 TLB_register_interface(attr
, name
, tattr
, 0);
833 /* register TLBs into the opposite registry view, too */
834 if(opposite
== KEY_WOW64_32KEY
||
835 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
836 TLB_register_interface(attr
, name
, tattr
, opposite
);
839 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
842 ITypeInfo_Release(tinfo
);
849 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
854 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
856 WCHAR subKeyName
[50];
859 /* the path to the type */
860 get_interface_key( guid
, subKeyName
);
862 /* Delete its bits */
863 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
866 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
867 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
868 RegDeleteKeyW(subKey
, TypeLibW
);
870 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
873 /******************************************************************************
874 * UnRegisterTypeLib [OLEAUT32.186]
875 * Removes information about a type library from the System Registry
882 HRESULT WINAPI
UnRegisterTypeLib(
883 REFGUID libid
, /* [in] Guid of the library */
884 WORD wVerMajor
, /* [in] major version */
885 WORD wVerMinor
, /* [in] minor version */
886 LCID lcid
, /* [in] locale id */
889 BSTR tlibPath
= NULL
;
892 WCHAR subKeyName
[50];
895 BOOL deleteOtherStuff
;
897 TYPEATTR
* typeAttr
= NULL
;
899 ITypeInfo
* typeInfo
= NULL
;
900 ITypeLib
* typeLib
= NULL
;
903 TRACE("(IID: %s)\n",debugstr_guid(libid
));
905 /* Create the path to the key */
906 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
908 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
910 TRACE("Unsupported syskind %i\n", syskind
);
911 result
= E_INVALIDARG
;
915 /* get the path to the typelib on disk */
916 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
917 result
= E_INVALIDARG
;
921 /* Try and open the key to the type library. */
922 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
923 result
= E_INVALIDARG
;
927 /* Try and load the type library */
928 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
929 result
= TYPE_E_INVALIDSTATE
;
933 /* remove any types registered with this typelib */
934 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
935 for (i
=0; i
<numTypes
; i
++) {
936 /* get the kind of type */
937 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
941 /* skip non-interfaces, and get type info for the type */
942 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
945 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
948 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
952 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
953 kind
== TKIND_DISPATCH
)
956 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
958 TLB_unregister_interface(&typeAttr
->guid
, 0);
960 /* unregister TLBs into the opposite registry view, too */
961 if(opposite
== KEY_WOW64_32KEY
||
962 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
963 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
968 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
970 if (typeInfo
) ITypeInfo_Release(typeInfo
);
974 /* Now, delete the type library path subkey */
975 get_lcid_subkey( lcid
, syskind
, subKeyName
);
976 RegDeleteKeyW(key
, subKeyName
);
977 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
978 RegDeleteKeyW(key
, subKeyName
);
980 /* check if there is anything besides the FLAGS/HELPDIR keys.
981 If there is, we don't delete them */
982 tmpLength
= ARRAY_SIZE(subKeyName
);
983 deleteOtherStuff
= TRUE
;
985 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
986 tmpLength
= ARRAY_SIZE(subKeyName
);
988 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
989 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
990 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
991 deleteOtherStuff
= FALSE
;
995 /* only delete the other parts of the key if we're absolutely sure */
996 if (deleteOtherStuff
) {
997 RegDeleteKeyW(key
, FLAGSW
);
998 RegDeleteKeyW(key
, HELPDIRW
);
1002 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
1003 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
1004 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
1008 SysFreeString(tlibPath
);
1009 if (typeLib
) ITypeLib_Release(typeLib
);
1010 if (key
) RegCloseKey(key
);
1014 /******************************************************************************
1015 * RegisterTypeLibForUser [OLEAUT32.442]
1016 * Adds information about a type library to the user registry
1018 * Docs: ITypeLib FAR * ptlib
1019 * Docs: OLECHAR FAR* szFullPath
1020 * Docs: OLECHAR FAR* szHelpDir
1026 HRESULT WINAPI
RegisterTypeLibForUser(
1027 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
1028 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
1029 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1032 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1033 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1034 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1037 /******************************************************************************
1038 * UnRegisterTypeLibForUser [OLEAUT32.443]
1039 * Removes information about a type library from the user registry
1045 HRESULT WINAPI
UnRegisterTypeLibForUser(
1046 REFGUID libid
, /* [in] GUID of the library */
1047 WORD wVerMajor
, /* [in] major version */
1048 WORD wVerMinor
, /* [in] minor version */
1049 LCID lcid
, /* [in] locale id */
1052 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1053 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1054 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1057 /*======================= ITypeLib implementation =======================*/
1059 typedef struct tagTLBGuid
{
1066 typedef struct tagTLBCustData
1073 /* data structure for import typelibs */
1074 typedef struct tagTLBImpLib
1076 int offset
; /* offset in the file (MSFT)
1077 offset in nametable (SLTG)
1078 just used to identify library while reading
1080 TLBGuid
*guid
; /* libid */
1081 BSTR name
; /* name */
1083 LCID lcid
; /* lcid of imported typelib */
1085 WORD wVersionMajor
; /* major version number */
1086 WORD wVersionMinor
; /* minor version number */
1088 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1089 NULL if not yet loaded */
1093 typedef struct tagTLBString
{
1099 /* internal ITypeLib data */
1100 typedef struct tagITypeLibImpl
1102 ITypeLib2 ITypeLib2_iface
;
1103 ITypeComp ITypeComp_iface
;
1104 ICreateTypeLib2 ICreateTypeLib2_iface
;
1115 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1116 * exported to the application as a UNICODE string.
1118 struct list string_list
;
1119 struct list name_list
;
1120 struct list guid_list
;
1122 const TLBString
*Name
;
1123 const TLBString
*DocString
;
1124 const TLBString
*HelpFile
;
1125 const TLBString
*HelpStringDll
;
1126 DWORD dwHelpContext
;
1127 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1128 struct tagITypeInfoImpl
**typeinfos
;
1129 struct list custdata_list
;
1130 struct list implib_list
;
1131 int ctTypeDesc
; /* number of items in type desc array */
1132 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1133 library. Only used while reading MSFT
1135 struct list ref_list
; /* list of ref types in this typelib */
1136 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1139 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1145 static const ITypeLib2Vtbl tlbvt
;
1146 static const ITypeCompVtbl tlbtcvt
;
1147 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1149 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1151 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1154 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1156 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1159 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1161 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1164 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1166 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1169 /* ITypeLib methods */
1170 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1171 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1173 /*======================= ITypeInfo implementation =======================*/
1175 /* data for referenced types */
1176 typedef struct tagTLBRefType
1178 INT index
; /* Type index for internal ref or for external ref
1179 it the format is SLTG. -2 indicates to
1183 TLBGuid
*guid
; /* guid of the referenced type */
1184 /* if index == TLB_REF_USE_GUID */
1186 HREFTYPE reference
; /* The href of this ref */
1187 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1188 TLB_REF_INTERNAL for internal refs
1189 TLB_REF_NOT_FOUND for broken refs */
1194 #define TLB_REF_USE_GUID -2
1196 #define TLB_REF_INTERNAL (void*)-2
1197 #define TLB_REF_NOT_FOUND (void*)-1
1199 /* internal Parameter data */
1200 typedef struct tagTLBParDesc
1202 const TLBString
*Name
;
1203 struct list custdata_list
;
1206 /* internal Function data */
1207 typedef struct tagTLBFuncDesc
1209 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1210 const TLBString
*Name
; /* the name of this function */
1211 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1213 int HelpStringContext
;
1214 const TLBString
*HelpString
;
1215 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1216 struct list custdata_list
;
1219 /* internal Variable data */
1220 typedef struct tagTLBVarDesc
1222 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1223 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1224 const TLBString
*Name
; /* the name of this variable */
1226 int HelpStringContext
;
1227 const TLBString
*HelpString
;
1228 struct list custdata_list
;
1231 /* internal implemented interface data */
1232 typedef struct tagTLBImplType
1234 HREFTYPE hRef
; /* hRef of interface */
1235 int implflags
; /* IMPLFLAG_*s */
1236 struct list custdata_list
;
1239 /* internal TypeInfo data */
1240 typedef struct tagITypeInfoImpl
1242 ITypeInfo2 ITypeInfo2_iface
;
1243 ITypeComp ITypeComp_iface
;
1244 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1246 BOOL not_attached_to_typelib
;
1251 TYPEDESC
*tdescAlias
;
1253 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1254 int index
; /* index in this typelib; */
1255 HREFTYPE hreftype
; /* hreftype for app object binding */
1256 /* type libs seem to store the doc strings in ascii
1257 * so why should we do it in unicode?
1259 const TLBString
*Name
;
1260 const TLBString
*DocString
;
1261 const TLBString
*DllName
;
1262 const TLBString
*Schema
;
1263 DWORD dwHelpContext
;
1264 DWORD dwHelpStringContext
;
1267 TLBFuncDesc
*funcdescs
;
1270 TLBVarDesc
*vardescs
;
1272 /* Implemented Interfaces */
1273 TLBImplType
*impltypes
;
1275 struct list
*pcustdata_list
;
1276 struct list custdata_list
;
1279 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1281 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1284 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1286 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1289 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1291 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1294 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1296 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1299 static const ITypeInfo2Vtbl tinfvt
;
1300 static const ITypeCompVtbl tcompvt
;
1301 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1303 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1304 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1306 typedef struct tagTLBContext
1308 unsigned int oStart
; /* start of TLB in file */
1309 unsigned int pos
; /* current pos */
1310 unsigned int length
; /* total length */
1311 void *mapping
; /* memory mapping */
1312 MSFT_SegDir
* pTblDir
;
1313 ITypeLibImpl
* pLibInfo
;
1317 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1319 return str
!= NULL
? str
->str
: NULL
;
1322 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1326 return memcmp(left
, str
->str
, len
);
1329 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1331 return guid
!= NULL
? &guid
->guid
: NULL
;
1334 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1336 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1339 static int get_ptr_size(SYSKIND syskind
)
1349 WARN("Unhandled syskind: 0x%x\n", syskind
);
1356 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1357 if (pTD
->vt
& VT_RESERVED
)
1358 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1359 if (pTD
->vt
& VT_BYREF
)
1360 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1361 if (pTD
->vt
& VT_ARRAY
)
1362 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1363 if (pTD
->vt
& VT_VECTOR
)
1364 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1365 switch(pTD
->vt
& VT_TYPEMASK
) {
1366 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1367 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1368 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1369 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1370 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1371 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1372 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1373 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1374 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1375 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1376 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1377 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1378 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1379 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1380 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1381 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1382 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1383 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1384 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1385 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1386 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1387 pTD
->u
.hreftype
); break;
1388 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1389 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1390 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1391 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1393 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1394 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1396 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1397 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1398 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1401 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1405 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1407 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1408 dump_TypeDesc(&edesc
->tdesc
,buf
);
1409 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1410 MESSAGE("\t\tu.paramdesc.wParamFlags");
1411 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1412 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1413 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1414 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1415 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1416 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1417 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1418 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1419 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1421 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1423 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1424 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1425 MESSAGE("Param %d:\n",i
);
1426 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1428 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1429 switch (funcdesc
->funckind
) {
1430 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1431 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1432 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1433 case FUNC_STATIC
: MESSAGE("static");break;
1434 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1435 default: MESSAGE("unknown");break;
1437 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1438 switch (funcdesc
->invkind
) {
1439 case INVOKE_FUNC
: MESSAGE("func");break;
1440 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1441 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1442 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1444 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1445 switch (funcdesc
->callconv
) {
1446 case CC_CDECL
: MESSAGE("cdecl");break;
1447 case CC_PASCAL
: MESSAGE("pascal");break;
1448 case CC_STDCALL
: MESSAGE("stdcall");break;
1449 case CC_SYSCALL
: MESSAGE("syscall");break;
1452 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1453 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1454 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1456 MESSAGE("\telemdescFunc (return value type):\n");
1457 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1460 static const char * const typekind_desc
[] =
1473 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1476 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1477 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1478 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1481 dump_FUNCDESC(&(pfd
->funcdesc
));
1483 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1484 if(pfd
->Entry
== NULL
)
1485 MESSAGE("\tentry: (null)\n");
1486 else if(pfd
->Entry
== (void*)-1)
1487 MESSAGE("\tentry: invalid\n");
1488 else if(IS_INTRESOURCE(pfd
->Entry
))
1489 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1491 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1493 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1497 dump_TLBFuncDescOne(pfd
);
1502 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1506 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1512 static void dump_TLBImpLib(const TLBImpLib
*import
)
1514 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1515 debugstr_w(import
->name
));
1516 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1517 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1520 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1524 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1526 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1527 if(ref
->index
== -1)
1528 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1530 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1532 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1534 TRACE_(typelib
)("in lib\n");
1535 dump_TLBImpLib(ref
->pImpTLInfo
);
1540 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1545 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1546 impl
->hRef
, impl
->implflags
);
1552 static void dump_DispParms(const DISPPARAMS
* pdp
)
1556 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1558 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1560 TRACE("named args:\n");
1561 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1562 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1565 if (pdp
->cArgs
&& pdp
->rgvarg
)
1568 for (index
= 0; index
< pdp
->cArgs
; index
++)
1569 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1573 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1575 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1576 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1577 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1578 TRACE("kind:%s\n", typekind_desc
[pty
->typeattr
.typekind
]);
1579 TRACE("fct:%u var:%u impl:%u\n", pty
->typeattr
.cFuncs
, pty
->typeattr
.cVars
, pty
->typeattr
.cImplTypes
);
1580 TRACE("wTypeFlags: 0x%04x\n", pty
->typeattr
.wTypeFlags
);
1581 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1582 if (pty
->typeattr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1584 dump_TLBFuncDesc(pty
->funcdescs
, pty
->typeattr
.cFuncs
);
1585 dump_TLBVarDesc(pty
->vardescs
, pty
->typeattr
.cVars
);
1586 dump_TLBImplType(pty
->impltypes
, pty
->typeattr
.cImplTypes
);
1589 static void dump_VARDESC(const VARDESC
*v
)
1591 MESSAGE("memid %d\n",v
->memid
);
1592 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1593 MESSAGE("oInst %d\n",v
->u
.oInst
);
1594 dump_ELEMDESC(&(v
->elemdescVar
));
1595 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1596 MESSAGE("varkind %d\n",v
->varkind
);
1599 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1601 /* VT_LPWSTR is largest type that, may appear in type description */
1602 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1603 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1604 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1605 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1606 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1607 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1608 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1609 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1612 static void TLB_abort(void)
1617 /* returns the size required for a deep copy of a typedesc into a
1619 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1623 if (alloc_initial_space
)
1624 size
+= sizeof(TYPEDESC
);
1630 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1633 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1634 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1640 /* deep copy a typedesc into a flat buffer */
1641 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1646 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1655 dest
->u
.lptdesc
= buffer
;
1656 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1659 dest
->u
.lpadesc
= buffer
;
1660 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1661 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1662 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1668 /* free custom data allocated by MSFT_CustData */
1669 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1671 TLBCustData
*cd
, *cdn
;
1672 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1674 list_remove(&cd
->entry
);
1675 VariantClear(&cd
->data
);
1680 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1685 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1686 ret
= SysAllocStringLen(NULL
, len
- 1);
1687 if (!ret
) return ret
;
1688 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1692 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1693 UINT n
, MEMBERID memid
)
1696 if(funcdescs
->funcdesc
.memid
== memid
)
1704 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1705 UINT n
, MEMBERID memid
)
1708 if(vardescs
->vardesc
.memid
== memid
)
1716 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1717 UINT n
, const OLECHAR
*name
)
1720 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1728 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1730 TLBCustData
*cust_data
;
1731 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1732 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1737 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1738 UINT n
, const OLECHAR
*name
)
1741 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1749 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1751 list_init(&var_desc
->custdata_list
);
1754 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1758 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1763 TLBVarDesc_Constructor(&ret
[n
-1]);
1770 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1774 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1779 list_init(&ret
[n
-1].custdata_list
);
1786 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1788 list_init(&func_desc
->custdata_list
);
1791 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1795 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1800 TLBFuncDesc_Constructor(&ret
[n
-1]);
1807 static void TLBImplType_Constructor(TLBImplType
*impl
)
1809 list_init(&impl
->custdata_list
);
1812 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1816 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1821 TLBImplType_Constructor(&ret
[n
-1]);
1828 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1829 const GUID
*new_guid
, HREFTYPE hreftype
)
1833 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1834 if (IsEqualGUID(&guid
->guid
, new_guid
))
1838 guid
= heap_alloc(sizeof(TLBGuid
));
1842 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1843 guid
->hreftype
= hreftype
;
1845 list_add_tail(guid_list
, &guid
->entry
);
1850 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1852 TLBCustData
*cust_data
;
1864 return DISP_E_BADVARTYPE
;
1867 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1870 cust_data
= heap_alloc(sizeof(TLBCustData
));
1872 return E_OUTOFMEMORY
;
1874 cust_data
->guid
= tlbguid
;
1875 VariantInit(&cust_data
->data
);
1877 list_add_tail(custdata_list
, &cust_data
->entry
);
1879 VariantClear(&cust_data
->data
);
1881 return VariantCopy(&cust_data
->data
, var
);
1884 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1891 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1892 if (strcmpW(str
->str
, new_str
) == 0)
1896 str
= heap_alloc(sizeof(TLBString
));
1900 str
->str
= SysAllocString(new_str
);
1906 list_add_tail(string_list
, &str
->entry
);
1911 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1912 ULONG
*size
, WORD
*align
)
1918 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1922 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1924 ITypeInfo_Release(other
);
1929 *size
= attr
->cbSizeInstance
;
1931 *align
= attr
->cbAlignment
;
1933 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1934 ITypeInfo_Release(other
);
1939 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1940 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1942 ULONG i
, sub
, ptr_size
;
1945 ptr_size
= get_ptr_size(sys
);
1984 *size
= sizeof(DATE
);
1987 *size
= sizeof(VARIANT
);
1989 if(sys
== SYS_WIN32
)
1990 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1994 *size
= sizeof(DECIMAL
);
2001 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2002 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2003 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2008 case VT_USERDEFINED
:
2009 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2011 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2025 /**********************************************************************
2027 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2030 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2032 if (where
!= DO_NOT_SEEK
)
2034 where
+= pcx
->oStart
;
2035 if (where
> pcx
->length
)
2038 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2046 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2048 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2049 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2051 MSFT_Seek(pcx
, where
);
2052 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2053 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2058 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2063 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2064 FromLEDWords(buffer
, ret
);
2069 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2074 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2075 FromLEWords(buffer
, ret
);
2080 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2083 MSFT_GuidEntry entry
;
2086 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2088 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2091 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2093 guid
= heap_alloc(sizeof(TLBGuid
));
2095 guid
->offset
= offs
;
2096 guid
->guid
= entry
.guid
;
2097 guid
->hreftype
= entry
.hreftype
;
2099 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2101 offs
+= sizeof(MSFT_GuidEntry
);
2105 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2109 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2110 if(ret
->offset
== offset
){
2111 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2119 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2121 MSFT_NameIntro niName
;
2125 ERR_(typelib
)("bad offset %d\n", offset
);
2129 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2130 pcx
->pTblDir
->pNametab
.offset
+offset
);
2132 return niName
.hreftype
;
2135 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2138 MSFT_NameIntro intro
;
2140 int offs
= 0, lengthInChars
;
2142 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2146 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2149 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2150 intro
.namelen
&= 0xFF;
2151 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2153 len_piece
= (len_piece
+ 4) & ~0x3;
2157 string
= heap_alloc(len_piece
+ 1);
2158 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2159 string
[intro
.namelen
] = '\0';
2161 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2162 string
, -1, NULL
, 0);
2163 if (!lengthInChars
) {
2165 return E_UNEXPECTED
;
2168 tlbstr
= heap_alloc(sizeof(TLBString
));
2170 tlbstr
->offset
= offs
;
2171 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2172 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2176 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2182 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2186 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2187 if (tlbstr
->offset
== offset
) {
2188 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2196 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2200 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2201 if (tlbstr
->offset
== offset
) {
2202 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2211 * read a value and fill a VARIANT structure
2213 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2217 TRACE_(typelib
)("\n");
2219 if(offset
<0) { /* data are packed in here */
2220 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2221 V_I4(pVar
) = offset
& 0x3ffffff;
2224 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2225 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2226 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2227 switch (V_VT(pVar
)){
2228 case VT_EMPTY
: /* FIXME: is this right? */
2229 case VT_NULL
: /* FIXME: is this right? */
2230 case VT_I2
: /* this should not happen */
2241 case VT_VOID
: /* FIXME: is this right? */
2249 case VT_DECIMAL
: /* FIXME: is this right? */
2252 /* pointer types with known behaviour */
2255 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2257 V_BSTR(pVar
) = NULL
;
2259 ptr
= heap_alloc_zero(size
);
2260 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2261 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2262 /* FIXME: do we need a AtoW conversion here? */
2263 V_UNION(pVar
, bstrVal
[size
])='\0';
2264 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2269 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2276 case VT_USERDEFINED
:
2282 case VT_STREAMED_OBJECT
:
2283 case VT_STORED_OBJECT
:
2284 case VT_BLOB_OBJECT
:
2289 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2293 if(size
>0) /* (big|small) endian correct? */
2294 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2298 * create a linked list with custom data
2300 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2306 TRACE_(typelib
)("\n");
2308 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2312 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2313 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2314 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2315 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2316 list_add_head(custdata_list
, &pNew
->entry
);
2317 offset
= entry
.next
;
2322 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2325 pTd
->vt
=type
& VT_TYPEMASK
;
2327 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2329 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2332 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2334 return (invkind
== INVOKE_PROPERTYGET
||
2335 invkind
== INVOKE_PROPERTYPUT
||
2336 invkind
== INVOKE_PROPERTYPUTREF
);
2340 MSFT_DoFuncs(TLBContext
* pcx
,
2345 TLBFuncDesc
** pptfd
)
2348 * member information is stored in a data structure at offset
2349 * indicated by the memoffset field of the typeinfo structure
2350 * There are several distinctive parts.
2351 * The first part starts with a field that holds the total length
2352 * of this (first) part excluding this field. Then follow the records,
2353 * for each member there is one record.
2355 * The first entry is always the length of the record (including this
2357 * The rest of the record depends on the type of the member. If there is
2358 * a field indicating the member type (function, variable, interface, etc)
2359 * I have not found it yet. At this time we depend on the information
2360 * in the type info and the usual order how things are stored.
2362 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2365 * Third is an equal sized array with file offsets to the name entry
2368 * The fourth and last (?) part is an array with offsets to the records
2369 * in the first part of this file segment.
2372 int infolen
, nameoffset
, reclength
, i
;
2373 int recoffset
= offset
+ sizeof(INT
);
2375 char *recbuf
= heap_alloc(0xffff);
2376 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2377 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2379 TRACE_(typelib
)("\n");
2381 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2383 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2385 for ( i
= 0; i
< cFuncs
; i
++ )
2389 /* name, eventually add to a hash table */
2390 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2391 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2393 /* read the function information record */
2394 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2396 reclength
&= 0xffff;
2398 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2400 /* size without argument data */
2401 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2402 if (pFuncRec
->FKCCIC
& 0x1000)
2403 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2405 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2406 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2408 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2409 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2411 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2413 if (pFuncRec
->FKCCIC
& 0x2000 )
2415 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2416 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2417 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2420 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2423 ptfd
->Entry
= (TLBString
*)-1;
2425 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2426 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2428 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2429 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2431 /* fill the FuncDesc Structure */
2432 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2433 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2435 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2436 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2437 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2438 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2439 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2440 ptfd
->funcdesc
.oVft
= (pFuncRec
->VtableOffset
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
2441 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2443 /* nameoffset is sometimes -1 on the second half of a propget/propput
2444 * pair of functions */
2445 if ((nameoffset
== -1) && (i
> 0) &&
2446 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2447 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2448 ptfd
->Name
= ptfd_prev
->Name
;
2450 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2454 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2456 /* do the parameters/arguments */
2457 if(pFuncRec
->nrargs
)
2460 MSFT_ParameterInfo paraminfo
;
2462 ptfd
->funcdesc
.lprgelemdescParam
=
2463 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2465 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2467 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2468 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2470 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2472 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2478 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2481 if (paraminfo
.oName
!= -1)
2482 ptfd
->pParamDesc
[j
].Name
=
2483 MSFT_ReadName( pcx
, paraminfo
.oName
);
2484 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2487 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2488 (pFuncRec
->FKCCIC
& 0x1000) )
2490 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2492 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2494 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2496 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2497 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2499 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2503 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2506 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2507 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2508 pFuncRec
->FKCCIC
& 0x80 )
2511 pFuncRec
->oArgCustData
[j
],
2512 &ptfd
->pParamDesc
[j
].custdata_list
);
2515 /* SEEK value = jump to offset,
2516 * from there jump to the end of record,
2517 * go back by (j-1) arguments
2519 MSFT_ReadLEDWords( ¶minfo
,
2520 sizeof(MSFT_ParameterInfo
), pcx
,
2521 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2522 * sizeof(MSFT_ParameterInfo
)));
2526 /* scode is not used: archaic win16 stuff FIXME: right? */
2527 ptfd
->funcdesc
.cScodes
= 0 ;
2528 ptfd
->funcdesc
.lprgscode
= NULL
;
2532 recoffset
+= reclength
;
2537 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2538 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2540 int infolen
, nameoffset
, reclength
;
2542 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2547 TRACE_(typelib
)("\n");
2549 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2550 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2551 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2552 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2553 recoffset
+= offset
+sizeof(INT
);
2554 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2555 /* name, eventually add to a hash table */
2556 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2557 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2558 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2559 /* read the variable information record */
2560 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2562 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2565 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2566 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2568 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2569 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2571 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2572 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2574 /* fill the VarDesc Structure */
2575 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2576 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2577 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2578 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2579 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2580 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2581 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2582 if(pVarRec
->VarKind
== VAR_CONST
){
2583 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2584 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2585 pVarRec
->OffsValue
, pcx
);
2587 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2588 recoffset
+= reclength
;
2592 /* process Implemented Interfaces of a com class */
2593 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2597 MSFT_RefRecord refrec
;
2600 TRACE_(typelib
)("\n");
2602 pTI
->impltypes
= TLBImplType_Alloc(count
);
2603 pImpl
= pTI
->impltypes
;
2604 for(i
=0;i
<count
;i
++){
2605 if(offset
<0) break; /* paranoia */
2606 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2607 pImpl
->hRef
= refrec
.reftype
;
2608 pImpl
->implflags
=refrec
.flags
;
2609 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2610 offset
=refrec
.onext
;
2616 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2617 * and some structures, and fix the alignment */
2618 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2620 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2621 switch(info
->tdescAlias
->vt
){
2629 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2630 info
->typeattr
.cbAlignment
= sizeof(void*);
2633 case VT_USERDEFINED
:
2634 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2637 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2638 info
->typeattr
.cbAlignment
= 8;
2640 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2641 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2643 info
->typeattr
.cbAlignment
= sizeof(void*);
2646 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2647 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2648 info
->typeattr
.typekind
== TKIND_COCLASS
){
2649 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2650 info
->typeattr
.cbAlignment
= sizeof(void*);
2656 * process a typeinfo record
2658 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2661 ITypeLibImpl
* pLibInfo
)
2663 MSFT_TypeInfoBase tiBase
;
2664 ITypeInfoImpl
*ptiRet
;
2666 TRACE_(typelib
)("count=%u\n", count
);
2668 ptiRet
= ITypeInfoImpl_Constructor();
2669 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2670 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2672 /* this is where we are coming from */
2673 ptiRet
->pTypeLib
= pLibInfo
;
2674 ptiRet
->index
=count
;
2676 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2677 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2678 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2679 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2680 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2681 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2682 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2683 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2684 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2685 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2686 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2687 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2688 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
;
2689 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2691 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2692 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2693 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2697 /* IDLDESC idldescType; *//* never saw this one != zero */
2699 /* name, eventually add to a hash table */
2700 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2701 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2702 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2704 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2705 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2706 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2708 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2709 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2711 /* note: InfoType's Help file and HelpStringDll come from the containing
2712 * library. Further HelpString and Docstring appear to be the same thing :(
2715 if(ptiRet
->typeattr
.cFuncs
>0 )
2716 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2717 ptiRet
->typeattr
.cVars
,
2718 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2720 if(ptiRet
->typeattr
.cVars
>0 )
2721 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2722 ptiRet
->typeattr
.cVars
,
2723 tiBase
.memoffset
, &ptiRet
->vardescs
);
2724 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2725 switch(ptiRet
->typeattr
.typekind
)
2728 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2731 case TKIND_DISPATCH
:
2732 /* This is not -1 when the interface is a non-base dual interface or
2733 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2734 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2738 if (tiBase
.datatype1
!= -1)
2740 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2741 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2745 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2746 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2750 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2752 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2753 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2754 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2755 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2756 if (TRACE_ON(typelib
))
2757 dump_TypeInfo(ptiRet
);
2762 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2765 INT16 len_str
, len_piece
;
2766 int offs
= 0, lengthInChars
;
2768 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2772 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2775 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2776 len_piece
= len_str
+ sizeof(INT16
);
2778 len_piece
= (len_piece
+ 4) & ~0x3;
2782 string
= heap_alloc(len_piece
+ 1);
2783 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2784 string
[len_str
] = '\0';
2786 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2787 string
, -1, NULL
, 0);
2788 if (!lengthInChars
) {
2790 return E_UNEXPECTED
;
2793 tlbstr
= heap_alloc(sizeof(TLBString
));
2795 tlbstr
->offset
= offs
;
2796 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2797 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2801 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2807 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2812 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2813 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2814 MSFT_ImpInfo impinfo
;
2817 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2819 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2820 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2822 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2823 if(pImpLib
->offset
==impinfo
.oImpFile
)
2826 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2827 ref
->reference
= offs
;
2828 ref
->pImpTLInfo
= pImpLib
;
2829 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2830 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2831 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2832 ref
->index
= TLB_REF_USE_GUID
;
2834 ref
->index
= impinfo
.oGuid
;
2836 ERR("Cannot find a reference\n");
2837 ref
->reference
= -1;
2838 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2841 offs
+= sizeof(impinfo
);
2847 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2848 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2849 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2852 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2853 static CRITICAL_SECTION cache_section
;
2854 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2856 0, 0, &cache_section
,
2857 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2858 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2860 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2863 typedef struct TLB_PEFile
2865 IUnknown IUnknown_iface
;
2868 HRSRC typelib_resource
;
2869 HGLOBAL typelib_global
;
2870 LPVOID typelib_base
;
2873 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2875 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2878 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2880 if (IsEqualIID(riid
, &IID_IUnknown
))
2883 IUnknown_AddRef(iface
);
2887 return E_NOINTERFACE
;
2890 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2892 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2893 return InterlockedIncrement(&This
->refs
);
2896 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2898 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2899 ULONG refs
= InterlockedDecrement(&This
->refs
);
2902 if (This
->typelib_global
)
2903 FreeResource(This
->typelib_global
);
2905 FreeLibrary(This
->dll
);
2911 static const IUnknownVtbl TLB_PEFile_Vtable
=
2913 TLB_PEFile_QueryInterface
,
2918 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2921 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2923 This
= heap_alloc(sizeof(TLB_PEFile
));
2925 return E_OUTOFMEMORY
;
2927 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2930 This
->typelib_resource
= NULL
;
2931 This
->typelib_global
= NULL
;
2932 This
->typelib_base
= NULL
;
2934 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2935 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2939 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2940 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2941 if (This
->typelib_resource
)
2943 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2944 if (This
->typelib_global
)
2946 This
->typelib_base
= LockResource(This
->typelib_global
);
2948 if (This
->typelib_base
)
2950 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2951 *ppBase
= This
->typelib_base
;
2952 *ppFile
= &This
->IUnknown_iface
;
2958 TRACE("No TYPELIB resource found\n");
2962 TLB_PEFile_Release(&This
->IUnknown_iface
);
2966 typedef struct TLB_NEFile
2968 IUnknown IUnknown_iface
;
2970 LPVOID typelib_base
;
2973 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2975 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2978 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2980 if (IsEqualIID(riid
, &IID_IUnknown
))
2983 IUnknown_AddRef(iface
);
2987 return E_NOINTERFACE
;
2990 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2992 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2993 return InterlockedIncrement(&This
->refs
);
2996 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2998 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2999 ULONG refs
= InterlockedDecrement(&This
->refs
);
3002 heap_free(This
->typelib_base
);
3008 static const IUnknownVtbl TLB_NEFile_Vtable
=
3010 TLB_NEFile_QueryInterface
,
3015 /***********************************************************************
3016 * read_xx_header [internal]
3018 static int read_xx_header( HFILE lzfd
)
3020 IMAGE_DOS_HEADER mzh
;
3023 LZSeek( lzfd
, 0, SEEK_SET
);
3024 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3026 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3029 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3030 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3033 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3035 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3036 return IMAGE_OS2_SIGNATURE
;
3037 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3038 return IMAGE_NT_SIGNATURE
;
3041 WARN("Can't handle %s files.\n", magic
);
3046 /***********************************************************************
3047 * find_ne_resource [internal]
3049 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3050 DWORD
*resLen
, DWORD
*resOff
)
3052 IMAGE_OS2_HEADER nehd
;
3053 NE_TYPEINFO
*typeInfo
;
3054 NE_NAMEINFO
*nameInfo
;
3060 /* Read in NE header */
3061 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3062 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3064 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3067 TRACE("No resources in NE dll\n" );
3071 /* Read in resource table */
3072 resTab
= heap_alloc( resTabSize
);
3073 if ( !resTab
) return FALSE
;
3075 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3076 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3078 heap_free( resTab
);
3083 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3085 if (!IS_INTRESOURCE(typeid)) /* named type */
3087 BYTE len
= strlen( typeid );
3088 while (typeInfo
->type_id
)
3090 if (!(typeInfo
->type_id
& 0x8000))
3092 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3093 if ((*p
== len
) && !_strnicmp( (char*)p
+1, typeid, len
)) goto found_type
;
3095 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3096 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3099 else /* numeric type id */
3101 WORD id
= LOWORD(typeid) | 0x8000;
3102 while (typeInfo
->type_id
)
3104 if (typeInfo
->type_id
== id
) goto found_type
;
3105 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3106 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3109 TRACE("No typeid entry found for %p\n", typeid );
3110 heap_free( resTab
);
3114 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3116 if (!IS_INTRESOURCE(resid
)) /* named resource */
3118 BYTE len
= strlen( resid
);
3119 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3121 BYTE
*p
= resTab
+ nameInfo
->id
;
3122 if (nameInfo
->id
& 0x8000) continue;
3123 if ((*p
== len
) && !_strnicmp( (char*)p
+1, resid
, len
)) goto found_name
;
3126 else /* numeric resource id */
3128 WORD id
= LOWORD(resid
) | 0x8000;
3129 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3130 if (nameInfo
->id
== id
) goto found_name
;
3132 TRACE("No resid entry found for %p\n", typeid );
3133 heap_free( resTab
);
3137 /* Return resource data */
3138 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3139 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3141 heap_free( resTab
);
3145 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3149 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3152 This
= heap_alloc(sizeof(TLB_NEFile
));
3153 if (!This
) return E_OUTOFMEMORY
;
3155 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3157 This
->typelib_base
= NULL
;
3159 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3160 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3162 DWORD reslen
, offset
;
3163 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3165 This
->typelib_base
= heap_alloc(reslen
);
3166 if( !This
->typelib_base
)
3170 LZSeek( lzfd
, offset
, SEEK_SET
);
3171 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3173 *ppBase
= This
->typelib_base
;
3174 *pdwTLBLength
= reslen
;
3175 *ppFile
= &This
->IUnknown_iface
;
3181 if( lzfd
>= 0) LZClose( lzfd
);
3182 TLB_NEFile_Release(&This
->IUnknown_iface
);
3186 typedef struct TLB_Mapping
3188 IUnknown IUnknown_iface
;
3192 LPVOID typelib_base
;
3195 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3197 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3200 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3202 if (IsEqualIID(riid
, &IID_IUnknown
))
3205 IUnknown_AddRef(iface
);
3209 return E_NOINTERFACE
;
3212 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3214 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3215 return InterlockedIncrement(&This
->refs
);
3218 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3220 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3221 ULONG refs
= InterlockedDecrement(&This
->refs
);
3224 if (This
->typelib_base
)
3225 UnmapViewOfFile(This
->typelib_base
);
3227 CloseHandle(This
->mapping
);
3228 if (This
->file
!= INVALID_HANDLE_VALUE
)
3229 CloseHandle(This
->file
);
3235 static const IUnknownVtbl TLB_Mapping_Vtable
=
3237 TLB_Mapping_QueryInterface
,
3242 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3246 This
= heap_alloc(sizeof(TLB_Mapping
));
3248 return E_OUTOFMEMORY
;
3250 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3252 This
->file
= INVALID_HANDLE_VALUE
;
3253 This
->mapping
= NULL
;
3254 This
->typelib_base
= NULL
;
3256 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3257 if (INVALID_HANDLE_VALUE
!= This
->file
)
3259 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3262 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3263 if(This
->typelib_base
)
3265 /* retrieve file size */
3266 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3267 *ppBase
= This
->typelib_base
;
3268 *ppFile
= &This
->IUnknown_iface
;
3274 IUnknown_Release(&This
->IUnknown_iface
);
3275 return TYPE_E_CANTLOADLIBRARY
;
3278 /****************************************************************************
3281 * find the type of the typelib file and map the typelib resource into
3285 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3286 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3288 ITypeLibImpl
*entry
;
3291 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3292 LPVOID pBase
= NULL
;
3293 DWORD dwTLBLength
= 0;
3294 IUnknown
*pFile
= NULL
;
3299 index_str
= strrchrW(pszFileName
, '\\');
3300 if(index_str
&& *++index_str
!= '\0')
3303 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3304 if(*end_ptr
== '\0')
3306 int str_len
= index_str
- pszFileName
- 1;
3308 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3309 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3314 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3316 if(strchrW(file
, '\\'))
3318 lstrcpyW(pszPath
, file
);
3322 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3323 pszPath
[len
] = '\\';
3324 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3328 if(file
!= pszFileName
) heap_free(file
);
3330 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3331 if(h
!= INVALID_HANDLE_VALUE
){
3332 FILE_NAME_INFORMATION size_info
;
3335 /* GetFileInformationByHandleEx returns the path of the file without
3336 * WOW64 redirection */
3337 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, &size_info
, sizeof(size_info
));
3338 if(br
|| GetLastError() == ERROR_MORE_DATA
){
3339 FILE_NAME_INFORMATION
*info
;
3340 DWORD size
= sizeof(*info
) + size_info
.FileNameLength
+ sizeof(WCHAR
);
3342 info
= HeapAlloc(GetProcessHeap(), 0, size
);
3344 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, info
, size
);
3346 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3347 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3350 HeapFree(GetProcessHeap(), 0, info
);
3356 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3358 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3359 EnterCriticalSection(&cache_section
);
3360 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3362 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3364 TRACE("cache hit\n");
3365 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3366 ITypeLib2_AddRef(*ppTypeLib
);
3367 LeaveCriticalSection(&cache_section
);
3371 LeaveCriticalSection(&cache_section
);
3373 /* now actually load and parse the typelib */
3375 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3376 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3377 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3378 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3379 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3382 if (dwTLBLength
>= 4)
3384 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3385 if (dwSignature
== MSFT_SIGNATURE
)
3386 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3387 else if (dwSignature
== SLTG_SIGNATURE
)
3388 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3391 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3392 ret
= TYPE_E_CANTLOADLIBRARY
;
3396 ret
= TYPE_E_CANTLOADLIBRARY
;
3397 IUnknown_Release(pFile
);
3401 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3403 TRACE("adding to cache\n");
3404 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3405 lstrcpyW(impl
->path
, pszPath
);
3406 /* We should really canonicalise the path here. */
3407 impl
->index
= index
;
3409 /* FIXME: check if it has added already in the meantime */
3410 EnterCriticalSection(&cache_section
);
3411 list_add_head(&tlb_cache
, &impl
->entry
);
3412 LeaveCriticalSection(&cache_section
);
3418 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3420 ret
= TYPE_E_CANTLOADLIBRARY
;
3427 /*================== ITypeLib(2) Methods ===================================*/
3429 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3431 ITypeLibImpl
* pTypeLibImpl
;
3433 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3434 if (!pTypeLibImpl
) return NULL
;
3436 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3437 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3438 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3439 pTypeLibImpl
->ref
= 1;
3441 list_init(&pTypeLibImpl
->implib_list
);
3442 list_init(&pTypeLibImpl
->custdata_list
);
3443 list_init(&pTypeLibImpl
->name_list
);
3444 list_init(&pTypeLibImpl
->string_list
);
3445 list_init(&pTypeLibImpl
->guid_list
);
3446 list_init(&pTypeLibImpl
->ref_list
);
3447 pTypeLibImpl
->dispatch_href
= -1;
3449 return pTypeLibImpl
;
3452 /****************************************************************************
3453 * ITypeLib2_Constructor_MSFT
3455 * loading an MSFT typelib from an in-memory image
3457 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3461 MSFT_Header tlbHeader
;
3462 MSFT_SegDir tlbSegDir
;
3463 ITypeLibImpl
* pTypeLibImpl
;
3466 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3468 pTypeLibImpl
= TypeLibImpl_Constructor();
3469 if (!pTypeLibImpl
) return NULL
;
3471 /* get pointer to beginning of typelib data */
3475 cx
.pLibInfo
= pTypeLibImpl
;
3476 cx
.length
= dwTLBLength
;
3479 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3480 TRACE_(typelib
)("header:\n");
3481 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3482 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3483 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3486 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3488 /* there is a small amount of information here until the next important
3490 * the segment directory . Try to calculate the amount of data */
3491 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3493 /* now read the segment directory */
3494 TRACE("read segment directory (at %d)\n",lPSegDir
);
3495 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3496 cx
.pTblDir
= &tlbSegDir
;
3498 /* just check two entries */
3499 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3501 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3502 heap_free(pTypeLibImpl
);
3506 MSFT_ReadAllNames(&cx
);
3507 MSFT_ReadAllStrings(&cx
);
3508 MSFT_ReadAllGuids(&cx
);
3510 /* now fill our internal data */
3511 /* TLIBATTR fields */
3512 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3514 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3515 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3516 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3517 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3518 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3520 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3521 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3523 /* name, eventually add to a hash table */
3524 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3527 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3528 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3530 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3533 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3534 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3537 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3540 if(tlbHeader
.CustomDataOffset
>= 0)
3542 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3545 /* fill in type descriptions */
3546 if(tlbSegDir
.pTypdescTab
.length
> 0)
3548 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3550 pTypeLibImpl
->ctTypeDesc
= cTD
;
3551 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3552 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3555 /* FIXME: add several sanity checks here */
3556 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3557 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3559 /* FIXME: check safearray */
3561 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3563 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3565 else if(td
[0] == VT_CARRAY
)
3567 /* array descr table here */
3568 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3570 else if(td
[0] == VT_USERDEFINED
)
3572 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3574 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3577 /* second time around to fill the array subscript info */
3580 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3581 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3583 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3584 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3587 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3589 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3591 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3593 for(j
= 0; j
<td
[2]; j
++)
3595 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3596 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3597 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3598 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3603 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3604 ERR("didn't find array description data\n");
3609 /* imported type libs */
3610 if(tlbSegDir
.pImpFiles
.offset
>0)
3613 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3616 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3620 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3621 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3622 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3624 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3625 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3626 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3627 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3630 name
= heap_alloc_zero(size
+1);
3631 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3632 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3635 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3636 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3638 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3642 MSFT_ReadAllRefs(&cx
);
3644 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3647 if(tlbHeader
.nrtypeinfos
>= 0 )
3649 ITypeInfoImpl
**ppTI
;
3651 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3653 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3655 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3658 (pTypeLibImpl
->TypeInfoCount
)++;
3663 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3664 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3665 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3669 TRACE("(%p)\n", pTypeLibImpl
);
3670 return &pTypeLibImpl
->ITypeLib2_iface
;
3674 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3680 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3681 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3685 guid
->Data4
[0] = s
>> 8;
3686 guid
->Data4
[1] = s
& 0xff;
3689 for(i
= 0; i
< 6; i
++) {
3690 memcpy(b
, str
+ 24 + 2 * i
, 2);
3691 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3696 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3703 bytelen
= *(const WORD
*)ptr
;
3704 if(bytelen
== 0xffff) return 2;
3706 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3707 tmp_str
= SysAllocStringLen(NULL
, len
);
3709 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3710 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3711 SysFreeString(tmp_str
);
3716 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3721 bytelen
= *(const WORD
*)ptr
;
3722 if(bytelen
== 0xffff) return 2;
3723 *str
= heap_alloc(bytelen
+ 1);
3724 memcpy(*str
, ptr
+ 2, bytelen
);
3725 (*str
)[bytelen
] = '\0';
3729 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3734 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3735 if (tlbstr
->offset
== offset
)
3739 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3740 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3741 SysFreeString(tmp_str
);
3746 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3748 char *ptr
= pLibBlk
;
3751 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3752 FIXME("libblk magic = %04x\n", w
);
3757 if((w
= *(WORD
*)ptr
) != 0xffff) {
3758 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3763 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3765 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3767 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3770 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3771 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3774 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3775 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3777 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3780 ptr
+= 4; /* skip res12 */
3782 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3785 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3788 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3791 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3792 ptr
+= sizeof(GUID
);
3794 return ptr
- (char*)pLibBlk
;
3797 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3802 } sltg_ref_lookup_t
;
3804 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3805 HREFTYPE
*typelib_ref
)
3807 if(table
&& typeinfo_ref
< table
->num
)
3809 *typelib_ref
= table
->refs
[typeinfo_ref
];
3813 ERR_(typelib
)("Unable to find reference\n");
3818 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3823 if((*pType
& 0xe00) == 0xe00) {
3825 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3826 pTD
= pTD
->u
.lptdesc
;
3828 switch(*pType
& 0x3f) {
3831 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3832 pTD
= pTD
->u
.lptdesc
;
3835 case VT_USERDEFINED
:
3836 pTD
->vt
= VT_USERDEFINED
;
3837 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3843 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3846 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3848 pTD
->vt
= VT_CARRAY
;
3849 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3850 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3851 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3852 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3854 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3860 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3864 pTD
->vt
= VT_SAFEARRAY
;
3865 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3866 pTD
= pTD
->u
.lptdesc
;
3870 pTD
->vt
= *pType
& 0x3f;
3879 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3880 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3882 /* Handle [in/out] first */
3883 if((*pType
& 0xc000) == 0xc000)
3884 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3885 else if(*pType
& 0x8000)
3886 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3887 else if(*pType
& 0x4000)
3888 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3890 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3893 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3896 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3898 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3902 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3907 TLBRefType
*ref_type
;
3908 sltg_ref_lookup_t
*table
;
3909 HREFTYPE typelib_ref
;
3911 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3912 FIXME("Ref magic = %x\n", pRef
->magic
);
3915 name
= ( (char*)pRef
->names
+ pRef
->number
);
3917 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3918 table
->num
= pRef
->number
>> 3;
3920 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3922 /* We don't want the first href to be 0 */
3923 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3925 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3927 unsigned int lib_offs
, type_num
;
3929 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3931 name
+= SLTG_ReadStringA(name
, &refname
);
3932 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3933 FIXME_(typelib
)("Can't sscanf ref\n");
3934 if(lib_offs
!= 0xffff) {
3937 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3938 if(import
->offset
== lib_offs
)
3941 if(&import
->entry
== &pTL
->implib_list
) {
3942 char fname
[MAX_PATH
+1];
3946 import
= heap_alloc_zero(sizeof(*import
));
3947 import
->offset
= lib_offs
;
3948 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3949 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3950 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3951 &import
->wVersionMajor
,
3952 &import
->wVersionMinor
,
3953 &import
->lcid
, fname
) != 4) {
3954 FIXME_(typelib
)("can't sscanf ref %s\n",
3955 pNameTable
+ lib_offs
+ 40);
3957 len
= strlen(fname
);
3958 if(fname
[len
-1] != '#')
3959 FIXME("fname = %s\n", fname
);
3960 fname
[len
-1] = '\0';
3961 import
->name
= TLB_MultiByteToBSTR(fname
);
3962 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3964 ref_type
->pImpTLInfo
= import
;
3966 /* Store a reference to IDispatch */
3967 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3968 pTL
->dispatch_href
= typelib_ref
;
3970 } else { /* internal ref */
3971 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3973 ref_type
->reference
= typelib_ref
;
3974 ref_type
->index
= type_num
;
3977 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3979 table
->refs
[ref
] = typelib_ref
;
3982 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3983 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3984 dump_TLBRefType(pTL
);
3988 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3989 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3991 SLTG_ImplInfo
*info
;
3992 TLBImplType
*pImplType
;
3993 /* I don't really get this structure, usually it's 0x16 bytes
3994 long, but iuser.tlb contains some that are 0x18 bytes long.
3995 That's ok because we can use the next ptr to jump to the next
3996 one. But how do we know the length of the last one? The WORD
3997 at offs 0x8 might be the clue. For now I'm just assuming that
3998 the last one is the regular 0x16 bytes. */
4000 info
= (SLTG_ImplInfo
*)pBlk
;
4002 pTI
->typeattr
.cImplTypes
++;
4003 if(info
->next
== 0xffff)
4005 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4008 info
= (SLTG_ImplInfo
*)pBlk
;
4009 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
4010 pImplType
= pTI
->impltypes
;
4012 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4013 pImplType
->implflags
= info
->impltypeflags
;
4016 if(info
->next
== 0xffff)
4019 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4020 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4022 info
++; /* see comment at top of function */
4026 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4027 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4029 TLBVarDesc
*pVarDesc
;
4030 const TLBString
*prevName
= NULL
;
4031 SLTG_Variable
*pItem
;
4035 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4037 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4038 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4040 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4042 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4043 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4044 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4048 if (pItem
->name
== 0xfffe)
4049 pVarDesc
->Name
= prevName
;
4051 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4053 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4054 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4055 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4057 if(pItem
->flags
& 0x02)
4058 pType
= &pItem
->type
;
4060 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4062 if (pItem
->flags
& ~0xda)
4063 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4065 SLTG_DoElem(pType
, pBlk
,
4066 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4068 if (TRACE_ON(typelib
)) {
4070 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4071 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4074 if (pItem
->flags
& 0x40) {
4075 TRACE_(typelib
)("VAR_DISPATCH\n");
4076 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4078 else if (pItem
->flags
& 0x10) {
4079 TRACE_(typelib
)("VAR_CONST\n");
4080 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4081 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4082 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4083 if (pItem
->flags
& 0x08)
4084 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4086 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4092 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4094 TRACE_(typelib
)("len = %u\n", len
);
4095 if (len
== 0xffff) {
4098 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4099 str
= SysAllocStringLen(NULL
, alloc_len
);
4100 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4102 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4103 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4112 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4113 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4116 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4121 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4122 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4123 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4126 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4127 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4129 if (pItem
->flags
& 0x80)
4130 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4132 prevName
= pVarDesc
->Name
;
4134 pTI
->typeattr
.cVars
= cVars
;
4137 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4138 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4140 SLTG_Function
*pFunc
;
4142 TLBFuncDesc
*pFuncDesc
;
4144 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4146 pFuncDesc
= pTI
->funcdescs
;
4147 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4148 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4153 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4154 case SLTG_FUNCTION_MAGIC
:
4155 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4157 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4158 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4160 case SLTG_STATIC_FUNCTION_MAGIC
:
4161 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4164 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4167 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4169 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4170 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4171 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4172 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4173 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4174 pFuncDesc
->funcdesc
.oVft
= (pFunc
->vtblpos
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
4176 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4177 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4179 if(pFunc
->retnextopt
& 0x80)
4180 pType
= &pFunc
->rettype
;
4182 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4184 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4186 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4187 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4188 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4190 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4192 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4193 char *paramName
= pNameTable
+ *pArg
;
4195 /* If arg type follows then paramName points to the 2nd
4196 letter of the name, else the next WORD is an offset to
4197 the arg type and paramName points to the first letter.
4198 So let's take one char off paramName and see if we're
4199 pointing at an alpha-numeric char. However if *pArg is
4200 0xffff or 0xfffe then the param has no name, the former
4201 meaning that the next WORD is the type, the latter
4202 meaning that the next WORD is an offset to the type. */
4207 else if(*pArg
== 0xfffe) {
4211 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4216 if(HaveOffs
) { /* the next word is an offset to type */
4217 pType
= (WORD
*)(pBlk
+ *pArg
);
4218 SLTG_DoElem(pType
, pBlk
,
4219 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4224 pArg
= SLTG_DoElem(pArg
, pBlk
,
4225 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4228 /* Are we an optional param ? */
4229 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4230 pFuncDesc
->funcdesc
.cParamsOpt
)
4231 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4234 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4235 paramName
- pNameTable
, pTI
->pTypeLib
);
4237 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4241 pTI
->typeattr
.cFuncs
= cFuncs
;
4244 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4245 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4246 SLTG_TypeInfoTail
*pTITail
)
4249 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4251 if(pTIHeader
->href_table
!= 0xffffffff) {
4252 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4258 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4259 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4261 heap_free(ref_lookup
);
4265 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4266 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4267 const SLTG_TypeInfoTail
*pTITail
)
4270 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4272 if(pTIHeader
->href_table
!= 0xffffffff) {
4273 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4279 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4280 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4283 if (pTITail
->funcs_off
!= 0xffff)
4284 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4286 heap_free(ref_lookup
);
4288 if (TRACE_ON(typelib
))
4289 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4292 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4293 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4294 const SLTG_TypeInfoTail
*pTITail
)
4296 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4299 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4300 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4301 const SLTG_TypeInfoTail
*pTITail
)
4304 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4306 if (pTITail
->simple_alias
) {
4307 /* if simple alias, no more processing required */
4308 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4309 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4313 if(pTIHeader
->href_table
!= 0xffffffff) {
4314 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4318 /* otherwise it is an offset to a type */
4319 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4321 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4322 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4324 heap_free(ref_lookup
);
4327 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4328 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4329 const SLTG_TypeInfoTail
*pTITail
)
4331 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4332 if (pTIHeader
->href_table
!= 0xffffffff)
4333 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4336 if (pTITail
->vars_off
!= 0xffff)
4337 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4339 if (pTITail
->funcs_off
!= 0xffff)
4340 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4342 if (pTITail
->impls_off
!= 0xffff)
4343 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4345 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4346 * of dispinterface functions including the IDispatch ones, so
4347 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4348 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4350 heap_free(ref_lookup
);
4351 if (TRACE_ON(typelib
))
4352 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4355 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4356 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4357 const SLTG_TypeInfoTail
*pTITail
)
4359 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4362 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4363 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4364 const SLTG_TypeInfoTail
*pTITail
)
4366 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4367 if (pTIHeader
->href_table
!= 0xffffffff)
4368 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4371 if (pTITail
->vars_off
!= 0xffff)
4372 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4374 if (pTITail
->funcs_off
!= 0xffff)
4375 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4376 heap_free(ref_lookup
);
4377 if (TRACE_ON(typelib
))
4381 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4382 manageable copy of it into this */
4395 } SLTG_InternalOtherTypeInfo
;
4397 /****************************************************************************
4398 * ITypeLib2_Constructor_SLTG
4400 * loading a SLTG typelib from an in-memory image
4402 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4404 ITypeLibImpl
*pTypeLibImpl
;
4405 SLTG_Header
*pHeader
;
4406 SLTG_BlkEntry
*pBlkEntry
;
4410 LPVOID pBlk
, pFirstBlk
;
4411 SLTG_LibBlk
*pLibBlk
;
4412 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4413 char *pAfterOTIBlks
= NULL
;
4414 char *pNameTable
, *ptr
;
4417 ITypeInfoImpl
**ppTypeInfoImpl
;
4419 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4422 pTypeLibImpl
= TypeLibImpl_Constructor();
4423 if (!pTypeLibImpl
) return NULL
;
4427 TRACE_(typelib
)("header:\n");
4428 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4429 pHeader
->nrOfFileBlks
);
4430 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4431 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4432 pHeader
->SLTG_magic
);
4436 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4437 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4439 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4440 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4442 /* Next we have a magic block */
4443 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4445 /* Let's see if we're still in sync */
4446 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4447 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4448 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4451 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4452 sizeof(SLTG_DIR_MAGIC
))) {
4453 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4457 pIndex
= (SLTG_Index
*)(pMagic
+1);
4459 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4461 pFirstBlk
= pPad9
+ 1;
4463 /* We'll set up a ptr to the main library block, which is the last one. */
4465 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4466 pBlkEntry
[order
].next
!= 0;
4467 order
= pBlkEntry
[order
].next
- 1) {
4468 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4472 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4474 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4479 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4481 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4484 ptr
= (char*)pLibBlk
+ len
;
4486 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4490 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4492 w
= *(WORD
*)(ptr
+ 2);
4495 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4496 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4497 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4499 w
= *(WORD
*)(ptr
+ 4 + len
);
4501 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4503 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4504 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4505 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4507 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4508 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4509 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4511 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4512 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4515 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4516 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4517 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4518 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4519 len
+= sizeof(SLTG_OtherTypeInfo
);
4523 pAfterOTIBlks
= ptr
;
4525 /* Skip this WORD and get the next DWORD */
4526 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4528 /* Now add this to pLibBLk look at what we're pointing at and
4529 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4530 dust and we should be pointing at the beginning of the name
4533 pNameTable
= (char*)pLibBlk
+ len
;
4535 switch(*(WORD
*)pNameTable
) {
4542 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4546 pNameTable
+= 0x216;
4550 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4552 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4555 /* Hopefully we now have enough ptrs set up to actually read in
4556 some TypeInfos. It's not clear which order to do them in, so
4557 I'll just follow the links along the BlkEntry chain and read
4558 them in the order in which they are in the file */
4560 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4561 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4563 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4564 pBlkEntry
[order
].next
!= 0;
4565 order
= pBlkEntry
[order
].next
- 1, i
++) {
4567 SLTG_TypeInfoHeader
*pTIHeader
;
4568 SLTG_TypeInfoTail
*pTITail
;
4569 SLTG_MemberHeader
*pMemHeader
;
4571 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4572 FIXME_(typelib
)("Index strings don't match\n");
4573 heap_free(pOtherTypeInfoBlks
);
4578 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4579 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4580 heap_free(pOtherTypeInfoBlks
);
4583 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4584 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4585 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4587 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4588 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4589 (*ppTypeInfoImpl
)->index
= i
;
4590 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4591 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4592 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4593 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4594 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4595 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4596 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4597 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4599 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4600 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4602 if((pTIHeader
->typeflags1
& 7) != 2)
4603 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4604 if(pTIHeader
->typeflags3
!= 2)
4605 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4607 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4608 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4609 typekind_desc
[pTIHeader
->typekind
],
4610 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4611 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4613 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4615 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4617 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4618 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4619 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4621 switch(pTIHeader
->typekind
) {
4623 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4624 pTIHeader
, pTITail
);
4628 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4629 pTIHeader
, pTITail
);
4632 case TKIND_INTERFACE
:
4633 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4634 pTIHeader
, pTITail
);
4638 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4639 pTIHeader
, pTITail
);
4643 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4644 pTIHeader
, pTITail
);
4647 case TKIND_DISPATCH
:
4648 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4649 pTIHeader
, pTITail
);
4653 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4654 pTIHeader
, pTITail
);
4658 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4663 /* could get cFuncs, cVars and cImplTypes from here
4664 but we've already set those */
4665 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4681 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4684 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4685 FIXME("Somehow processed %d TypeInfos\n", i
);
4686 heap_free(pOtherTypeInfoBlks
);
4690 heap_free(pOtherTypeInfoBlks
);
4691 return &pTypeLibImpl
->ITypeLib2_iface
;
4694 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4696 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4698 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4700 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4701 IsEqualIID(riid
,&IID_ITypeLib
)||
4702 IsEqualIID(riid
,&IID_ITypeLib2
))
4704 *ppv
= &This
->ITypeLib2_iface
;
4706 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4707 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4709 *ppv
= &This
->ICreateTypeLib2_iface
;
4714 TRACE("-- Interface: E_NOINTERFACE\n");
4715 return E_NOINTERFACE
;
4718 IUnknown_AddRef((IUnknown
*)*ppv
);
4722 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4724 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4725 ULONG ref
= InterlockedIncrement(&This
->ref
);
4727 TRACE("(%p) ref=%u\n", This
, ref
);
4732 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4734 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4735 ULONG ref
= InterlockedDecrement(&This
->ref
);
4737 TRACE("(%p) ref=%u\n",This
, ref
);
4741 TLBImpLib
*pImpLib
, *pImpLibNext
;
4742 TLBRefType
*ref_type
, *ref_type_next
;
4743 TLBString
*tlbstr
, *tlbstr_next
;
4744 TLBGuid
*tlbguid
, *tlbguid_next
;
4747 /* remove cache entry */
4750 TRACE("removing from cache list\n");
4751 EnterCriticalSection(&cache_section
);
4752 if(This
->entry
.next
)
4753 list_remove(&This
->entry
);
4754 LeaveCriticalSection(&cache_section
);
4755 heap_free(This
->path
);
4757 TRACE(" destroying ITypeLib(%p)\n",This
);
4759 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4760 list_remove(&tlbstr
->entry
);
4761 SysFreeString(tlbstr
->str
);
4765 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4766 list_remove(&tlbstr
->entry
);
4767 SysFreeString(tlbstr
->str
);
4771 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4772 list_remove(&tlbguid
->entry
);
4776 TLB_FreeCustData(&This
->custdata_list
);
4778 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4779 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4780 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4782 heap_free(This
->pTypeDesc
);
4784 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4786 if (pImpLib
->pImpTypeLib
)
4787 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4788 SysFreeString(pImpLib
->name
);
4790 list_remove(&pImpLib
->entry
);
4794 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, ref_type_next
, &This
->ref_list
, TLBRefType
, entry
)
4796 list_remove(&ref_type
->entry
);
4797 heap_free(ref_type
);
4800 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4801 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4802 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4804 heap_free(This
->typeinfos
);
4812 /* ITypeLib::GetTypeInfoCount
4814 * Returns the number of type descriptions in the type library
4816 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4818 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4819 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4820 return This
->TypeInfoCount
;
4823 /* ITypeLib::GetTypeInfo
4825 * retrieves the specified type description in the library.
4827 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4830 ITypeInfo
**ppTInfo
)
4832 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4834 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4837 return E_INVALIDARG
;
4839 if(index
>= This
->TypeInfoCount
)
4840 return TYPE_E_ELEMENTNOTFOUND
;
4842 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4843 ITypeInfo_AddRef(*ppTInfo
);
4849 /* ITypeLibs::GetTypeInfoType
4851 * Retrieves the type of a type description.
4853 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4858 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4860 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4863 return E_INVALIDARG
;
4865 if(index
>= This
->TypeInfoCount
)
4866 return TYPE_E_ELEMENTNOTFOUND
;
4868 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4873 /* ITypeLib::GetTypeInfoOfGuid
4875 * Retrieves the type description that corresponds to the specified GUID.
4878 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4881 ITypeInfo
**ppTInfo
)
4883 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4886 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4888 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4889 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4890 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4891 ITypeInfo_AddRef(*ppTInfo
);
4896 return TYPE_E_ELEMENTNOTFOUND
;
4899 /* ITypeLib::GetLibAttr
4901 * Retrieves the structure that contains the library's attributes.
4904 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4908 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4910 TRACE("(%p, %p)\n", This
, attr
);
4912 if (!attr
) return E_INVALIDARG
;
4914 *attr
= heap_alloc(sizeof(**attr
));
4915 if (!*attr
) return E_OUTOFMEMORY
;
4917 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4918 (*attr
)->lcid
= This
->set_lcid
;
4919 (*attr
)->syskind
= This
->syskind
;
4920 (*attr
)->wMajorVerNum
= This
->ver_major
;
4921 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4922 (*attr
)->wLibFlags
= This
->libflags
;
4927 /* ITypeLib::GetTypeComp
4929 * Enables a client compiler to bind to a library's types, variables,
4930 * constants, and global functions.
4933 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4935 ITypeComp
**ppTComp
)
4937 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4939 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4940 *ppTComp
= &This
->ITypeComp_iface
;
4941 ITypeComp_AddRef(*ppTComp
);
4946 /* ITypeLib::GetDocumentation
4948 * Retrieves the library's documentation string, the complete Help file name
4949 * and path, and the context identifier for the library Help topic in the Help
4952 * On a successful return all non-null BSTR pointers will have been set,
4955 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4959 BSTR
*pBstrDocString
,
4960 DWORD
*pdwHelpContext
,
4961 BSTR
*pBstrHelpFile
)
4963 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4964 HRESULT result
= E_INVALIDARG
;
4967 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4969 pBstrName
, pBstrDocString
,
4970 pdwHelpContext
, pBstrHelpFile
);
4974 /* documentation for the typelib */
4979 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4987 if (This
->DocString
)
4989 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4993 *pBstrDocString
= NULL
;
4997 *pdwHelpContext
= This
->dwHelpContext
;
5003 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5007 *pBstrHelpFile
= NULL
;
5014 /* for a typeinfo */
5015 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5017 if(SUCCEEDED(result
))
5019 result
= ITypeInfo_GetDocumentation(pTInfo
,
5023 pdwHelpContext
, pBstrHelpFile
);
5025 ITypeInfo_Release(pTInfo
);
5030 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5032 if (pBstrName
) SysFreeString (*pBstrName
);
5034 return STG_E_INSUFFICIENTMEMORY
;
5039 * Indicates whether a passed-in string contains the name of a type or member
5040 * described in the library.
5043 static HRESULT WINAPI
ITypeLib2_fnIsName(
5049 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5051 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5053 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5057 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5058 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5059 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5060 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5061 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5063 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5064 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5065 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5066 goto ITypeLib2_fnIsName_exit
;
5069 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5070 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5071 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5077 ITypeLib2_fnIsName_exit
:
5078 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5079 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5084 /* ITypeLib::FindName
5086 * Finds occurrences of a type description in a type library. This may be used
5087 * to quickly verify that a name exists in a type library.
5090 static HRESULT WINAPI
ITypeLib2_fnFindName(
5094 ITypeInfo
**ppTInfo
,
5098 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5103 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5105 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5106 return E_INVALIDARG
;
5108 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5109 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5110 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5114 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5115 memid
[count
] = MEMBERID_NIL
;
5116 goto ITypeLib2_fnFindName_exit
;
5119 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5120 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5122 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5123 memid
[count
] = func
->funcdesc
.memid
;
5124 goto ITypeLib2_fnFindName_exit
;
5128 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->typeattr
.cVars
, name
);
5130 memid
[count
] = var
->vardesc
.memid
;
5131 goto ITypeLib2_fnFindName_exit
;
5135 ITypeLib2_fnFindName_exit
:
5136 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5137 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5140 TRACE("found %d typeinfos\n", count
);
5147 /* ITypeLib::ReleaseTLibAttr
5149 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5152 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5154 TLIBATTR
*pTLibAttr
)
5156 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5157 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5158 heap_free(pTLibAttr
);
5161 /* ITypeLib2::GetCustData
5163 * gets the custom data
5165 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5170 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5171 TLBCustData
*pCData
;
5173 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5175 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5177 return TYPE_E_ELEMENTNOTFOUND
;
5179 VariantInit(pVarVal
);
5180 VariantCopy(pVarVal
, &pCData
->data
);
5185 /* ITypeLib2::GetLibStatistics
5187 * Returns statistics about a type library that are required for efficient
5188 * sizing of hash tables.
5191 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5193 ULONG
*pcUniqueNames
,
5194 ULONG
*pcchUniqueNames
)
5196 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5198 FIXME("(%p): stub!\n", This
);
5200 if(pcUniqueNames
) *pcUniqueNames
=1;
5201 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5205 /* ITypeLib2::GetDocumentation2
5207 * Retrieves the library's documentation string, the complete Help file name
5208 * and path, the localization context to use, and the context ID for the
5209 * library Help topic in the Help file.
5212 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5216 BSTR
*pbstrHelpString
,
5217 DWORD
*pdwHelpStringContext
,
5218 BSTR
*pbstrHelpStringDll
)
5220 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5224 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5226 /* the help string should be obtained from the helpstringdll,
5227 * using the _DLLGetDocumentation function, based on the supplied
5228 * lcid. Nice to do sometime...
5232 /* documentation for the typelib */
5234 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5235 if(pdwHelpStringContext
)
5236 *pdwHelpStringContext
=This
->dwHelpContext
;
5237 if(pbstrHelpStringDll
)
5238 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5244 /* for a typeinfo */
5245 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5247 if(SUCCEEDED(result
))
5249 ITypeInfo2
* pTInfo2
;
5250 result
= ITypeInfo_QueryInterface(pTInfo
,
5252 (LPVOID
*) &pTInfo2
);
5254 if(SUCCEEDED(result
))
5256 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5260 pdwHelpStringContext
,
5261 pbstrHelpStringDll
);
5263 ITypeInfo2_Release(pTInfo2
);
5266 ITypeInfo_Release(pTInfo
);
5272 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5274 TLBCustData
*pCData
;
5278 ct
= list_count(custdata_list
);
5280 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5281 if(!pCustData
->prgCustData
)
5282 return E_OUTOFMEMORY
;
5284 pCustData
->cCustData
= ct
;
5286 cdi
= pCustData
->prgCustData
;
5287 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5288 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5289 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5297 /* ITypeLib2::GetAllCustData
5299 * Gets all custom data items for the library.
5302 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5304 CUSTDATA
*pCustData
)
5306 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5307 TRACE("(%p)->(%p)\n", This
, pCustData
);
5308 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5311 static const ITypeLib2Vtbl tlbvt
= {
5312 ITypeLib2_fnQueryInterface
,
5314 ITypeLib2_fnRelease
,
5315 ITypeLib2_fnGetTypeInfoCount
,
5316 ITypeLib2_fnGetTypeInfo
,
5317 ITypeLib2_fnGetTypeInfoType
,
5318 ITypeLib2_fnGetTypeInfoOfGuid
,
5319 ITypeLib2_fnGetLibAttr
,
5320 ITypeLib2_fnGetTypeComp
,
5321 ITypeLib2_fnGetDocumentation
,
5323 ITypeLib2_fnFindName
,
5324 ITypeLib2_fnReleaseTLibAttr
,
5326 ITypeLib2_fnGetCustData
,
5327 ITypeLib2_fnGetLibStatistics
,
5328 ITypeLib2_fnGetDocumentation2
,
5329 ITypeLib2_fnGetAllCustData
5333 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5335 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5337 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5340 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5342 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5344 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5347 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5349 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5351 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5354 static HRESULT WINAPI
ITypeLibComp_fnBind(
5359 ITypeInfo
** ppTInfo
,
5360 DESCKIND
* pDescKind
,
5363 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5364 BOOL typemismatch
= FALSE
;
5367 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5369 *pDescKind
= DESCKIND_NONE
;
5370 pBindPtr
->lptcomp
= NULL
;
5373 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5374 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5375 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5377 /* FIXME: check wFlags here? */
5378 /* FIXME: we should use a hash table to look this info up using lHash
5379 * instead of an O(n) search */
5380 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5381 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5383 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5385 *pDescKind
= DESCKIND_TYPECOMP
;
5386 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5387 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5388 TRACE("module or enum: %s\n", debugstr_w(szName
));
5393 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5394 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5396 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5399 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5400 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5402 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5405 else if (hr
== TYPE_E_TYPEMISMATCH
)
5406 typemismatch
= TRUE
;
5409 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5410 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5412 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5414 ITypeInfo
*subtypeinfo
;
5416 DESCKIND subdesckind
;
5418 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5419 &subtypeinfo
, &subdesckind
, &subbindptr
);
5420 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5422 TYPEDESC tdesc_appobject
;
5423 const VARDESC vardesc_appobject
=
5426 NULL
, /* lpstrSchema */
5441 VAR_STATIC
/* varkind */
5444 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5445 tdesc_appobject
.vt
= VT_USERDEFINED
;
5447 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5449 /* cleanup things filled in by Bind call so we can put our
5450 * application object data in there instead */
5451 switch (subdesckind
)
5453 case DESCKIND_FUNCDESC
:
5454 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5456 case DESCKIND_VARDESC
:
5457 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5462 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5464 if (pTypeInfo
->hreftype
== -1)
5465 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5467 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5471 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5472 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5473 ITypeInfo_AddRef(*ppTInfo
);
5476 else if (hr
== TYPE_E_TYPEMISMATCH
)
5477 typemismatch
= TRUE
;
5483 TRACE("type mismatch %s\n", debugstr_w(szName
));
5484 return TYPE_E_TYPEMISMATCH
;
5488 TRACE("name not found %s\n", debugstr_w(szName
));
5493 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5497 ITypeInfo
** ppTInfo
,
5498 ITypeComp
** ppTComp
)
5500 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5501 ITypeInfoImpl
*info
;
5503 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5505 if(!szName
|| !ppTInfo
|| !ppTComp
)
5506 return E_INVALIDARG
;
5508 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5515 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5516 ITypeInfo_AddRef(*ppTInfo
);
5517 *ppTComp
= &info
->ITypeComp_iface
;
5518 ITypeComp_AddRef(*ppTComp
);
5523 static const ITypeCompVtbl tlbtcvt
=
5526 ITypeLibComp_fnQueryInterface
,
5527 ITypeLibComp_fnAddRef
,
5528 ITypeLibComp_fnRelease
,
5530 ITypeLibComp_fnBind
,
5531 ITypeLibComp_fnBindType
5534 /*================== ITypeInfo(2) Methods ===================================*/
5535 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5537 ITypeInfoImpl
*pTypeInfoImpl
;
5539 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5542 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5543 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5544 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5545 pTypeInfoImpl
->ref
= 0;
5546 pTypeInfoImpl
->hreftype
= -1;
5547 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5548 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5549 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5550 list_init(pTypeInfoImpl
->pcustdata_list
);
5552 TRACE("(%p)\n", pTypeInfoImpl
);
5553 return pTypeInfoImpl
;
5556 /* ITypeInfo::QueryInterface
5558 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5563 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5565 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5568 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5569 IsEqualIID(riid
,&IID_ITypeInfo
)||
5570 IsEqualIID(riid
,&IID_ITypeInfo2
))
5571 *ppvObject
= &This
->ITypeInfo2_iface
;
5572 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5573 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5574 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5575 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5576 *ppvObject
= &This
->ITypeComp_iface
;
5579 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5580 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5583 TRACE("-- Interface: E_NOINTERFACE\n");
5584 return E_NOINTERFACE
;
5587 /* ITypeInfo::AddRef
5589 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5591 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5592 ULONG ref
= InterlockedIncrement(&This
->ref
);
5594 TRACE("(%p)->ref is %u\n",This
, ref
);
5596 if (ref
== 1 /* incremented from 0 */)
5597 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5602 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5606 TRACE("destroying ITypeInfo(%p)\n",This
);
5608 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5611 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5612 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5614 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5615 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5616 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5617 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5619 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5620 heap_free(pFInfo
->pParamDesc
);
5621 TLB_FreeCustData(&pFInfo
->custdata_list
);
5623 heap_free(This
->funcdescs
);
5625 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5627 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5628 if (pVInfo
->vardesc_create
) {
5629 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5630 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5631 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5632 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5634 TLB_FreeCustData(&pVInfo
->custdata_list
);
5636 heap_free(This
->vardescs
);
5638 if(This
->impltypes
){
5639 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5640 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5641 TLB_FreeCustData(&pImpl
->custdata_list
);
5643 heap_free(This
->impltypes
);
5646 TLB_FreeCustData(&This
->custdata_list
);
5651 /* ITypeInfo::Release
5653 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5655 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5656 ULONG ref
= InterlockedDecrement(&This
->ref
);
5658 TRACE("(%p)->(%u)\n",This
, ref
);
5662 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5663 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5664 if (not_attached_to_typelib
)
5666 /* otherwise This will be freed when typelib is freed */
5672 /* ITypeInfo::GetTypeAttr
5674 * Retrieves a TYPEATTR structure that contains the attributes of the type
5678 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5679 LPTYPEATTR
*ppTypeAttr
)
5681 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5684 TRACE("(%p)\n",This
);
5686 size
= sizeof(**ppTypeAttr
);
5687 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5688 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5690 *ppTypeAttr
= heap_alloc(size
);
5692 return E_OUTOFMEMORY
;
5694 **ppTypeAttr
= This
->typeattr
;
5695 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5697 if (This
->tdescAlias
)
5698 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5700 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5701 /* This should include all the inherited funcs */
5702 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5703 /* This is always the size of IDispatch's vtbl */
5704 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5705 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5710 /* ITypeInfo::GetTypeComp
5712 * Retrieves the ITypeComp interface for the type description, which enables a
5713 * client compiler to bind to the type description's members.
5716 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5717 ITypeComp
* *ppTComp
)
5719 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5721 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5723 *ppTComp
= &This
->ITypeComp_iface
;
5724 ITypeComp_AddRef(*ppTComp
);
5728 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5730 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5731 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5732 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5736 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5739 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5740 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5742 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5743 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5744 *buffer
+= sizeof(PARAMDESCEX
);
5745 *pparamdescex_dest
= *pparamdescex_src
;
5746 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5747 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5748 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5749 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5752 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5756 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5758 UINT len
= SysStringLen(str
), i
;
5759 for (i
= 0; i
< len
; ++i
)
5765 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5767 if (V_VT(var
) == VT_INT
)
5768 return VariantChangeType(var
, var
, 0, VT_I4
);
5769 else if (V_VT(var
) == VT_UINT
)
5770 return VariantChangeType(var
, var
, 0, VT_UI4
);
5771 else if (V_VT(var
) == VT_BSTR
)
5772 return TLB_SanitizeBSTR(V_BSTR(var
));
5777 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5779 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5780 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5783 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5787 SIZE_T size
= sizeof(*src
);
5791 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5792 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5793 for (i
= 0; i
< src
->cParams
; i
++)
5795 size
+= sizeof(ELEMDESC
);
5796 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5799 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5800 if (!dest
) return E_OUTOFMEMORY
;
5803 if (dispinterface
) /* overwrite funckind */
5804 dest
->funckind
= FUNC_DISPATCH
;
5805 buffer
= (char *)(dest
+ 1);
5807 dest
->oVft
= dest
->oVft
& 0xFFFC;
5809 if (dest
->cScodes
) {
5810 dest
->lprgscode
= (SCODE
*)buffer
;
5811 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5812 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5814 dest
->lprgscode
= NULL
;
5816 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5819 SysFreeString((BSTR
)dest
);
5823 if (dest
->cParams
) {
5824 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5825 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5826 for (i
= 0; i
< src
->cParams
; i
++)
5828 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5834 /* undo the above actions */
5835 for (i
= i
- 1; i
>= 0; i
--)
5836 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5837 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5838 SysFreeString((BSTR
)dest
);
5842 dest
->lprgelemdescParam
= NULL
;
5844 /* special treatment for dispinterfaces: this makes functions appear
5845 * to return their [retval] value when it is really returning an
5847 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5849 if (dest
->cParams
&&
5850 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5852 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5853 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5855 ERR("elemdesc should have started with VT_PTR instead of:\n");
5857 dump_ELEMDESC(elemdesc
);
5858 return E_UNEXPECTED
;
5861 /* copy last parameter to the return value. we are using a flat
5862 * buffer so there is no danger of leaking memory in
5864 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5866 /* remove the last parameter */
5870 /* otherwise this function is made to appear to have no return
5872 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5880 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5882 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5883 if (var_desc
->varkind
== VAR_CONST
)
5884 VariantClear(var_desc
->u
.lpvarValue
);
5885 SysFreeString((BSTR
)var_desc
);
5888 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5890 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5892 if (index
>= This
->typeattr
.cFuncs
)
5893 return TYPE_E_ELEMENTNOTFOUND
;
5895 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5899 /* internal function to make the inherited interfaces' methods appear
5900 * part of the interface */
5901 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5902 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5904 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5906 UINT implemented_funcs
= 0;
5911 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5915 ITypeInfo
*pSubTypeInfo
;
5918 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5922 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5925 &sub_funcs
, hrefoffset
);
5926 implemented_funcs
+= sub_funcs
;
5927 ITypeInfo_Release(pSubTypeInfo
);
5930 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5934 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5938 if (index
< implemented_funcs
)
5939 return E_INVALIDARG
;
5940 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5944 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5946 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5949 switch (pTypeDesc
->vt
)
5951 case VT_USERDEFINED
:
5952 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5956 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5959 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5967 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5970 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5971 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5972 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5975 /* ITypeInfo::GetFuncDesc
5977 * Retrieves the FUNCDESC structure that contains information about a
5978 * specified function.
5981 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5982 LPFUNCDESC
*ppFuncDesc
)
5984 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5985 const FUNCDESC
*internal_funcdesc
;
5987 UINT hrefoffset
= 0;
5989 TRACE("(%p) index %d\n", This
, index
);
5992 return E_INVALIDARG
;
5994 if (This
->needs_layout
)
5995 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5997 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5998 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5999 &internal_funcdesc
, NULL
,
6002 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6003 &internal_funcdesc
);
6006 WARN("description for function %d not found\n", index
);
6010 hr
= TLB_AllocAndInitFuncDesc(
6013 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6015 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
6016 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6018 TRACE("-- 0x%08x\n", hr
);
6022 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6026 SIZE_T size
= sizeof(*src
);
6029 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6030 if (src
->varkind
== VAR_CONST
)
6031 size
+= sizeof(VARIANT
);
6032 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6034 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6035 if (!dest
) return E_OUTOFMEMORY
;
6038 buffer
= (char *)(dest
+ 1);
6039 if (src
->lpstrSchema
)
6042 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6043 len
= strlenW(src
->lpstrSchema
);
6044 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6045 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6048 if (src
->varkind
== VAR_CONST
)
6052 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6053 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6054 buffer
+= sizeof(VARIANT
);
6055 VariantInit(dest
->u
.lpvarValue
);
6056 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6059 SysFreeString((BSTR
)dest
);
6063 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6066 if (src
->varkind
== VAR_CONST
)
6067 VariantClear(dest
->u
.lpvarValue
);
6068 SysFreeString((BSTR
)dest
);
6075 /* ITypeInfo::GetVarDesc
6077 * Retrieves a VARDESC structure that describes the specified variable.
6080 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6081 LPVARDESC
*ppVarDesc
)
6083 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6084 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6086 TRACE("(%p) index %d\n", This
, index
);
6088 if(index
>= This
->typeattr
.cVars
)
6089 return TYPE_E_ELEMENTNOTFOUND
;
6091 if (This
->needs_layout
)
6092 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6094 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6097 /* ITypeInfo_GetNames
6099 * Retrieves the variable with the specified member ID (or the name of the
6100 * property or method and its parameters) that correspond to the specified
6103 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6104 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6106 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6107 const TLBFuncDesc
*pFDesc
;
6108 const TLBVarDesc
*pVDesc
;
6110 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6113 return E_INVALIDARG
;
6117 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
6120 if(!cMaxNames
|| !pFDesc
->Name
)
6123 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6126 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6127 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6129 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6135 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
6138 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6143 if(This
->impltypes
&&
6144 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
6145 /* recursive search */
6148 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6149 if(SUCCEEDED(result
))
6151 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6152 ITypeInfo_Release(pTInfo
);
6155 WARN("Could not search inherited interface!\n");
6159 WARN("no names found\n");
6162 return TYPE_E_ELEMENTNOTFOUND
;
6168 /* ITypeInfo::GetRefTypeOfImplType
6170 * If a type description describes a COM class, it retrieves the type
6171 * description of the implemented interface types. For an interface,
6172 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6176 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6181 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6184 TRACE("(%p) index %d\n", This
, index
);
6185 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6189 /* only valid on dual interfaces;
6190 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6193 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6199 hr
= TYPE_E_ELEMENTNOTFOUND
;
6202 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6204 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6205 *pRefType
= This
->pTypeLib
->dispatch_href
;
6209 if(index
>= This
->typeattr
.cImplTypes
)
6210 hr
= TYPE_E_ELEMENTNOTFOUND
;
6212 *pRefType
= This
->impltypes
[index
].hRef
;
6213 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6221 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6223 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6229 /* ITypeInfo::GetImplTypeFlags
6231 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6232 * or base interface in a type description.
6234 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6235 UINT index
, INT
*pImplTypeFlags
)
6237 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6239 TRACE("(%p) index %d\n", This
, index
);
6242 return E_INVALIDARG
;
6244 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6245 *pImplTypeFlags
= 0;
6249 if(index
>= This
->typeattr
.cImplTypes
)
6250 return TYPE_E_ELEMENTNOTFOUND
;
6252 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6258 * Maps between member names and member IDs, and parameter names and
6261 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6262 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6264 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6265 const TLBVarDesc
*pVDesc
;
6269 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6272 /* init out parameters in case of failure */
6273 for (i
= 0; i
< cNames
; i
++)
6274 pMemId
[i
] = MEMBERID_NIL
;
6276 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6278 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6279 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6280 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6281 for(i
=1; i
< cNames
; i
++){
6282 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6283 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6285 if( j
<pFDesc
->funcdesc
.cParams
)
6288 ret
=DISP_E_UNKNOWNNAME
;
6290 TRACE("-- 0x%08x\n", ret
);
6294 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, *rgszNames
);
6297 *pMemId
= pVDesc
->vardesc
.memid
;
6300 /* not found, see if it can be found in an inherited interface */
6301 if(This
->impltypes
) {
6302 /* recursive search */
6304 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6306 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6307 ITypeInfo_Release(pTInfo
);
6310 WARN("Could not search inherited interface!\n");
6312 WARN("no names found\n");
6313 return DISP_E_UNKNOWNNAME
;
6319 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6320 extern double call_double_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6321 __ASM_GLOBAL_FUNC( call_method
,
6323 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6324 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6325 "movl %esp,%ebp\n\t"
6326 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6328 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6330 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6331 "movl 12(%ebp),%edx\n\t"
6332 "movl %esp,%edi\n\t"
6335 "subl %edx,%edi\n\t"
6336 "andl $~15,%edi\n\t"
6337 "movl %edi,%esp\n\t"
6338 "movl 12(%ebp),%ecx\n\t"
6339 "movl 16(%ebp),%esi\n\t"
6342 "1:\tcall *8(%ebp)\n\t"
6343 "subl %esp,%edi\n\t"
6344 "movl 20(%ebp),%ecx\n\t"
6345 "movl %edi,(%ecx)\n\t"
6346 "leal -8(%ebp),%esp\n\t"
6348 __ASM_CFI(".cfi_same_value %edi\n\t")
6350 __ASM_CFI(".cfi_same_value %esi\n\t")
6352 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6353 __ASM_CFI(".cfi_same_value %ebp\n\t")
6355 __ASM_GLOBAL_FUNC( call_double_method
,
6356 "jmp " __ASM_NAME("call_method") )
6358 #elif defined(__x86_64__)
6360 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6361 extern double CDECL
call_double_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6362 __ASM_GLOBAL_FUNC( call_method
,
6364 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6365 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6366 "movq %rsp,%rbp\n\t"
6367 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6369 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6371 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6372 "movq %rcx,%rax\n\t"
6375 "cmovgq %rdx,%rcx\n\t"
6376 "leaq 0(,%rcx,8),%rdx\n\t"
6377 "subq %rdx,%rsp\n\t"
6378 "andq $~15,%rsp\n\t"
6379 "movq %rsp,%rdi\n\t"
6382 "movq 0(%rsp),%rcx\n\t"
6383 "movq 8(%rsp),%rdx\n\t"
6384 "movq 16(%rsp),%r8\n\t"
6385 "movq 24(%rsp),%r9\n\t"
6386 "movq 0(%rsp),%xmm0\n\t"
6387 "movq 8(%rsp),%xmm1\n\t"
6388 "movq 16(%rsp),%xmm2\n\t"
6389 "movq 24(%rsp),%xmm3\n\t"
6391 "leaq -16(%rbp),%rsp\n\t"
6393 __ASM_CFI(".cfi_same_value %rdi\n\t")
6395 __ASM_CFI(".cfi_same_value %rsi\n\t")
6396 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6398 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6399 __ASM_CFI(".cfi_same_value %rbp\n\t")
6401 __ASM_GLOBAL_FUNC( call_double_method
,
6402 "jmp " __ASM_NAME("call_method") )
6404 #elif defined(__arm__)
6406 extern LONGLONG CDECL
call_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6407 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6408 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6409 __ASM_GLOBAL_FUNC( call_method
,
6412 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6413 * 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)
6416 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6417 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6419 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6420 "beq 1f\n\t" /* Skip allocation if no stack args */
6421 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6422 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6423 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6424 "subs r1, r1, #4\n\t" /* Decrement count */
6425 "bgt 2b\n\t" /* Loop till done */
6429 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6431 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6432 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6434 "blx ip\n\t" /* Call the target function */
6436 "mov sp, fp\n\t" /* Clean the stack using fp */
6437 "pop {fp, pc}\n\t" /* Restore fp and return */
6439 __ASM_GLOBAL_FUNC( call_float_method
,
6440 "b " __ASM_NAME("call_method") )
6441 __ASM_GLOBAL_FUNC( call_double_method
,
6442 "b " __ASM_NAME("call_method") )
6444 #endif /* __arm__ */
6446 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6449 ITypeInfo
*tinfo2
= NULL
;
6450 TYPEATTR
*tattr
= NULL
;
6452 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6455 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6457 tdesc
->u
.hreftype
, hr
);
6460 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6463 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6464 ITypeInfo_Release(tinfo2
);
6468 switch (tattr
->typekind
)
6475 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6478 case TKIND_INTERFACE
:
6479 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6485 case TKIND_DISPATCH
:
6494 FIXME("TKIND_RECORD unhandled.\n");
6499 FIXME("TKIND_UNION unhandled.\n");
6504 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6508 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6509 ITypeInfo_Release(tinfo2
);
6513 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6517 /* enforce only one level of pointer indirection */
6518 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6520 tdesc
= tdesc
->u
.lptdesc
;
6522 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6523 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6524 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6525 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6526 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6528 VARTYPE vt_userdefined
= 0;
6529 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6530 if (tdesc
->vt
== VT_PTR
)
6532 vt_userdefined
= VT_BYREF
;
6533 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6535 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6537 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6538 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6540 *vt
|= vt_userdefined
;
6552 case VT_USERDEFINED
:
6553 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6560 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6561 hr
= DISP_E_BADVARTYPE
;
6565 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6580 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, HREFTYPE href
, GUID
*guid
)
6587 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
6591 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6593 ITypeInfo_Release(tinfo2
);
6597 switch(tattr
->typekind
) {
6599 hres
= get_iface_guid(tinfo2
, tattr
->tdescAlias
.u
.hreftype
, guid
);
6602 case TKIND_INTERFACE
:
6603 case TKIND_DISPATCH
:
6604 *guid
= tattr
->guid
;
6608 for (i
= 0; i
< tattr
->cImplTypes
; i
++)
6610 ITypeInfo_GetImplTypeFlags(tinfo2
, i
, &flags
);
6611 if (flags
& IMPLTYPEFLAG_FDEFAULT
)
6615 if (i
== tattr
->cImplTypes
)
6618 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo2
, i
, &href
);
6619 if (SUCCEEDED(hres
))
6620 hres
= get_iface_guid(tinfo2
, href
, guid
);
6624 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6625 hres
= E_UNEXPECTED
;
6628 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6629 ITypeInfo_Release(tinfo2
);
6633 /***********************************************************************
6634 * DispCallFunc (OLEAUT32.@)
6636 * Invokes a function of the specified calling convention, passing the
6637 * specified arguments and returns the result.
6640 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6641 * oVft [I] The offset in the vtable. See notes.
6642 * cc [I] Calling convention of the function to call.
6643 * vtReturn [I] The return type of the function.
6644 * cActuals [I] Number of parameters.
6645 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6646 * prgpvarg [I] The arguments to pass.
6647 * pvargResult [O] The return value of the function. Can be NULL.
6651 * Failure: HRESULT code.
6654 * The HRESULT return value of this function is not affected by the return
6655 * value of the user supplied function, which is returned in pvargResult.
6657 * If pvInstance is NULL then a non-object function is to be called and oVft
6658 * is the address of the function to call.
6660 * The cc parameter can be one of the following values:
6673 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6674 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6677 int argspos
= 0, stack_offset
;
6682 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6683 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6684 pvargResult
, V_VT(pvargResult
));
6686 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6688 FIXME("unsupported calling convention %d\n",cc
);
6689 return E_INVALIDARG
;
6692 /* maximum size for an argument is sizeof(VARIANT) */
6693 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6697 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6698 func
= vtable
[oVft
/sizeof(void *)];
6699 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6701 else func
= (void *)oVft
;
6707 args
[argspos
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6710 WARN("invalid return type %u\n", vtReturn
);
6712 return E_INVALIDARG
;
6717 for (i
= 0; i
< cActuals
; i
++)
6719 VARIANT
*arg
= prgpvarg
[i
];
6730 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6731 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6735 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6736 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6738 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6739 args
[argspos
++] = V_BOOL(arg
);
6742 args
[argspos
++] = V_UI4(arg
);
6745 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6753 call_method( func
, argspos
, args
, &stack_offset
);
6756 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6760 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6765 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6768 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6772 if (stack_offset
&& cc
== CC_STDCALL
)
6774 WARN( "stack pointer off by %d\n", stack_offset
);
6775 return DISP_E_BADCALLEE
;
6777 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6778 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6781 #elif defined(__x86_64__)
6787 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6788 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6789 pvargResult
, V_VT(pvargResult
));
6791 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6793 FIXME("unsupported calling convention %d\n",cc
);
6794 return E_INVALIDARG
;
6797 /* maximum size for an argument is sizeof(DWORD_PTR) */
6798 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6802 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6803 func
= vtable
[oVft
/sizeof(void *)];
6804 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6806 else func
= (void *)oVft
;
6812 args
[argspos
++] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6815 WARN("invalid return type %u\n", vtReturn
);
6817 return E_INVALIDARG
;
6822 for (i
= 0; i
< cActuals
; i
++)
6824 VARIANT
*arg
= prgpvarg
[i
];
6830 args
[argspos
++] = (ULONG_PTR
)arg
;
6832 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6833 args
[argspos
++] = V_BOOL(arg
);
6836 args
[argspos
++] = V_UI8(arg
);
6839 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6845 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
);
6849 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
);
6853 call_method( func
, argspos
, args
);
6856 V_UI8(pvargResult
) = call_method( func
, argspos
, args
);
6860 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6861 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6864 #elif defined(__arm__)
6878 int rcount
; /* 32-bit register index count */
6880 int scount
= 0; /* single-precision float register index count */
6881 int dcount
= 0; /* double-precision float register index count */
6884 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6885 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6887 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6889 FIXME("unsupported calling convention %d\n",cc
);
6890 return E_INVALIDARG
;
6898 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6899 func
= vtable
[oVft
/sizeof(void *)];
6900 regs
.r
[rcount
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6902 else func
= (void *)oVft
;
6904 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6905 /* first as it will need to be in the 'r' registers: */
6910 regs
.r
[rcount
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6913 WARN("invalid return type %u\n", vtReturn
);
6914 return E_INVALIDARG
;
6915 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6919 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6920 args
= heap_alloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 4 );
6922 for (i
= 0; i
< cActuals
; i
++)
6924 VARIANT
*arg
= prgpvarg
[i
];
6925 DWORD
*pdwarg
= (DWORD
*)(arg
); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6926 int ntemp
; /* Used for counting words split between registers and stack */
6932 case VT_R8
: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6935 dcount
= max( (scount
+ 1) / 2, dcount
);
6938 regs
.sd
.d
[dcount
++] = V_R8(arg
);
6942 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6943 memcpy( &args
[argspos
], &V_R8(arg
), sizeof(V_R8(arg
)) );
6944 argspos
+= sizeof(V_R8(arg
)) / sizeof(DWORD
);
6948 case VT_I8
: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6953 rcount
+= (rcount
% 2); /* align rcount to 8-byte register pair */
6954 memcpy( ®s
.r
[rcount
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6955 rcount
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6959 rcount
= 4; /* Make sure we flag that all 'r' regs are full */
6960 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6961 memcpy( &args
[argspos
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6962 argspos
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6965 case VT_DECIMAL
: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6967 /* 8-byte align 'r' and/or stack: */
6969 rcount
+= (rcount
% 2);
6973 argspos
+= (argspos
% 2);
6975 ntemp
= sizeof(*arg
) / sizeof(DWORD
);
6979 regs
.r
[rcount
++] = *pdwarg
++;
6981 args
[argspos
++] = *pdwarg
++;
6985 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6987 regs
.r
[rcount
++] = V_BOOL(arg
);
6989 args
[argspos
++] = V_BOOL(arg
);
6991 case VT_R4
: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6993 if (!(scount
% 2)) scount
= max( scount
, dcount
* 2 );
6995 regs
.sd
.s
[scount
++] = V_R4(arg
);
6997 args
[argspos
++] = V_UI4(arg
);
7002 regs
.r
[rcount
++] = V_UI4(arg
);
7004 args
[argspos
++] = V_UI4(arg
);
7007 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
7010 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 8-byte */
7014 case VT_EMPTY
: /* EMPTY = no return value */
7015 case VT_DECIMAL
: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
7017 call_method( func
, argspos
, args
, (DWORD
*)®s
);
7020 V_R4(pvargResult
) = call_float_method( func
, argspos
, args
, (DWORD
*)®s
);
7024 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, (DWORD
*)®s
);
7029 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
7032 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
7036 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
7037 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
7041 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7042 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
7047 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
7049 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
7052 #define INVBUF_ELEMENT_SIZE \
7053 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7054 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7055 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7056 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7057 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7058 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7059 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7060 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7062 static HRESULT WINAPI
ITypeInfo_fnInvoke(
7067 DISPPARAMS
*pDispParams
,
7068 VARIANT
*pVarResult
,
7069 EXCEPINFO
*pExcepInfo
,
7072 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7074 unsigned int var_index
;
7077 const TLBFuncDesc
*pFuncInfo
;
7080 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7081 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
7084 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7085 return DISP_E_MEMBERNOTFOUND
;
7089 ERR("NULL pDispParams not allowed\n");
7090 return E_INVALIDARG
;
7093 dump_DispParms(pDispParams
);
7095 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7097 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7098 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7099 return E_INVALIDARG
;
7102 /* we do this instead of using GetFuncDesc since it will return a fake
7103 * FUNCDESC for dispinterfaces and we want the real function description */
7104 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7105 pFuncInfo
= &This
->funcdescs
[fdc
];
7106 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7107 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7108 !func_restricted( &pFuncInfo
->funcdesc
))
7112 if (fdc
< This
->typeattr
.cFuncs
) {
7113 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7117 TRACE("invoking:\n");
7118 dump_TLBFuncDescOne(pFuncInfo
);
7121 switch (func_desc
->funckind
) {
7122 case FUNC_PUREVIRTUAL
:
7123 case FUNC_VIRTUAL
: {
7124 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7126 VARIANT retval
; /* pointer for storing byref retvals in */
7127 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7128 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7129 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7130 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7131 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7132 UINT vargs_converted
=0;
7136 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7138 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7140 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7141 hres
= DISP_E_PARAMNOTFOUND
;
7146 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7148 ERR("functions with the vararg attribute do not support named arguments\n");
7149 hres
= DISP_E_NONAMEDARGS
;
7153 for (i
= 0; i
< func_desc
->cParams
; i
++)
7155 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7156 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7161 TRACE("changing args\n");
7162 for (i
= 0; i
< func_desc
->cParams
; i
++)
7164 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7165 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7166 VARIANTARG
*src_arg
;
7168 if (wParamFlags
& PARAMFLAG_FLCID
)
7171 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7173 V_I4(arg
) = This
->pTypeLib
->lcid
;
7182 for (j
= 0; j
< cNamedArgs
; j
++)
7183 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7185 src_arg
= &pDispParams
->rgvarg
[j
];
7190 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7192 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7196 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7198 /* under most conditions the caller is not allowed to
7199 * pass in a dispparam arg in the index of what would be
7200 * the retval parameter. however, there is an exception
7201 * where the extra parameter is used in an extra
7202 * IDispatch::Invoke below */
7203 if ((i
< pDispParams
->cArgs
) &&
7204 ((func_desc
->cParams
!= 1) || !pVarResult
||
7205 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7207 hres
= DISP_E_BADPARAMCOUNT
;
7211 /* note: this check is placed so that if the caller passes
7212 * in a VARIANTARG for the retval we just ignore it, like
7214 if (i
== func_desc
->cParams
- 1)
7217 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7218 memset(arg
, 0, sizeof(*arg
));
7219 V_VT(arg
) = rgvt
[i
];
7220 memset(&retval
, 0, sizeof(retval
));
7221 V_BYREF(arg
) = &retval
;
7225 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7226 hres
= E_UNEXPECTED
;
7230 else if (src_arg
&& !((wParamFlags
& PARAMFLAG_FOPT
) &&
7231 V_VT(src_arg
) == VT_ERROR
&& V_ERROR(src_arg
) == DISP_E_PARAMNOTFOUND
))
7233 TRACE("%s\n", debugstr_variant(src_arg
));
7235 if(rgvt
[i
]!=V_VT(src_arg
))
7237 if (rgvt
[i
] == VT_VARIANT
)
7238 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7239 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7241 if (rgvt
[i
] == V_VT(src_arg
))
7242 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7245 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7246 if (wParamFlags
& PARAMFLAG_FIN
)
7247 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7248 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7250 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7252 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7255 SAFEARRAYBOUND bound
;
7259 bound
.cElements
= pDispParams
->cArgs
-i
;
7260 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7262 ERR("SafeArrayCreate failed\n");
7265 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7268 ERR("SafeArrayAccessData failed with %x\n", hres
);
7269 SafeArrayDestroy(a
);
7272 for (j
= 0; j
< bound
.cElements
; j
++)
7273 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7274 hres
= SafeArrayUnaccessData(a
);
7277 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7278 SafeArrayDestroy(a
);
7281 if (rgvt
[i
] & VT_BYREF
)
7282 V_BYREF(&rgvarg
[i
]) = &a
;
7284 V_ARRAY(&rgvarg
[i
]) = a
;
7285 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7287 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7289 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7290 if (wParamFlags
& PARAMFLAG_FIN
)
7291 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7293 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7294 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7295 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7297 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7299 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7300 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7304 /* FIXME: this doesn't work for VT_BYREF arguments if
7305 * they are not the same type as in the paramdesc */
7306 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7307 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7308 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7313 ERR("failed to convert param %d to %s from %s\n", i
,
7314 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7317 prgpvarg
[i
] = &rgvarg
[i
];
7321 prgpvarg
[i
] = src_arg
;
7324 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7325 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7326 && V_UNKNOWN(prgpvarg
[i
])) {
7327 IUnknown
*userdefined_iface
;
7330 if (tdesc
->vt
== VT_PTR
)
7331 tdesc
= tdesc
->u
.lptdesc
;
7333 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->u
.hreftype
, &guid
);
7337 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7339 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7343 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7344 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7347 else if (wParamFlags
& PARAMFLAG_FOPT
)
7350 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7351 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7353 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7359 VARIANTARG
*missing_arg
;
7360 /* if the function wants a pointer to a variant then
7361 * set that up, otherwise just pass the VT_ERROR in
7362 * the argument by value */
7363 if (rgvt
[i
] & VT_BYREF
)
7365 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7366 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7367 V_VARIANTREF(arg
) = missing_arg
;
7371 V_VT(missing_arg
) = VT_ERROR
;
7372 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7377 hres
= DISP_E_BADPARAMCOUNT
;
7381 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7383 /* VT_VOID is a special case for return types, so it is not
7384 * handled in the general function */
7385 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7386 V_VT(&varresult
) = VT_EMPTY
;
7389 V_VT(&varresult
) = 0;
7390 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7391 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7394 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7395 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7396 prgpvarg
, &varresult
);
7398 vargs_converted
= 0;
7400 for (i
= 0; i
< func_desc
->cParams
; i
++)
7402 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7403 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7405 if (wParamFlags
& PARAMFLAG_FLCID
)
7407 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7409 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7413 VariantInit(pVarResult
);
7414 /* deref return value */
7415 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7418 VARIANT_ClearInd(prgpvarg
[i
]);
7420 else if (vargs_converted
< pDispParams
->cArgs
)
7422 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7423 if (wParamFlags
& PARAMFLAG_FOUT
)
7425 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7427 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7431 ERR("failed to convert param %d to vt %d\n", i
,
7432 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7437 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7438 func_desc
->cParamsOpt
< 0 &&
7439 i
== func_desc
->cParams
-1)
7441 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7444 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7447 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7450 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7453 ERR("SafeArrayAccessData failed with %x\n", hres
);
7456 for (j
= 0; j
<= ubound
; j
++)
7457 VariantClear(&v
[j
]);
7458 hres
= SafeArrayUnaccessData(a
);
7461 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7465 VariantClear(&rgvarg
[i
]);
7468 else if (wParamFlags
& PARAMFLAG_FOPT
)
7470 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7471 VariantClear(&rgvarg
[i
]);
7474 VariantClear(&missing_arg
[i
]);
7477 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7479 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7480 hres
= DISP_E_EXCEPTION
;
7483 IErrorInfo
*pErrorInfo
;
7484 pExcepInfo
->scode
= V_ERROR(&varresult
);
7485 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7487 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7488 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7489 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7490 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7492 IErrorInfo_Release(pErrorInfo
);
7496 if (V_VT(&varresult
) != VT_ERROR
)
7498 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7502 VariantClear(pVarResult
);
7503 *pVarResult
= varresult
;
7506 VariantClear(&varresult
);
7509 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7510 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7511 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7512 (pDispParams
->cArgs
!= 0))
7514 if (V_VT(pVarResult
) == VT_DISPATCH
)
7516 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7517 /* Note: not VariantClear; we still need the dispatch
7518 * pointer to be valid */
7519 VariantInit(pVarResult
);
7520 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7521 GetSystemDefaultLCID(), wFlags
,
7522 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7523 IDispatch_Release(pDispatch
);
7527 VariantClear(pVarResult
);
7528 hres
= DISP_E_NOTACOLLECTION
;
7536 case FUNC_DISPATCH
: {
7539 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7540 if (SUCCEEDED(hres
)) {
7541 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7542 hres
= IDispatch_Invoke(
7543 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7544 pVarResult
,pExcepInfo
,pArgErr
7547 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7548 IDispatch_Release(disp
);
7550 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7554 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7559 TRACE("-- 0x%08x\n", hres
);
7562 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7565 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7566 if(FAILED(hres
)) return hres
;
7568 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7569 dump_VARDESC(var_desc
);
7570 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7574 /* not found, look for it in inherited interfaces */
7575 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7576 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7577 if(This
->impltypes
) {
7578 /* recursive search */
7580 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7581 if(SUCCEEDED(hres
)){
7582 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7583 ITypeInfo_Release(pTInfo
);
7586 WARN("Could not search inherited interface!\n");
7589 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7590 return DISP_E_MEMBERNOTFOUND
;
7593 /* ITypeInfo::GetDocumentation
7595 * Retrieves the documentation string, the complete Help file name and path,
7596 * and the context ID for the Help topic for a specified type description.
7598 * (Can be tested by the Visual Basic Editor in Word for instance.)
7600 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7601 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7602 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7604 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7605 const TLBFuncDesc
*pFDesc
;
7606 const TLBVarDesc
*pVDesc
;
7607 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7608 " HelpContext(%p) HelpFile(%p)\n",
7609 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7610 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7612 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7614 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7616 *pdwHelpContext
=This
->dwHelpContext
;
7618 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7620 }else {/* for a member */
7621 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7624 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7626 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7628 *pdwHelpContext
=pFDesc
->helpcontext
;
7630 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7633 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
7636 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7638 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7640 *pdwHelpContext
=pVDesc
->HelpContext
;
7642 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7647 if(This
->impltypes
&&
7648 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7649 /* recursive search */
7652 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7653 if(SUCCEEDED(result
)) {
7654 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7655 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7656 ITypeInfo_Release(pTInfo
);
7659 WARN("Could not search inherited interface!\n");
7662 WARN("member %d not found\n", memid
);
7663 return TYPE_E_ELEMENTNOTFOUND
;
7666 /* ITypeInfo::GetDllEntry
7668 * Retrieves a description or specification of an entry point for a function
7671 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7672 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7675 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7676 const TLBFuncDesc
*pFDesc
;
7678 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7680 if (pBstrDllName
) *pBstrDllName
= NULL
;
7681 if (pBstrName
) *pBstrName
= NULL
;
7682 if (pwOrdinal
) *pwOrdinal
= 0;
7684 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7685 return TYPE_E_BADMODULEKIND
;
7687 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7689 dump_TypeInfo(This
);
7691 dump_TLBFuncDescOne(pFDesc
);
7694 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7696 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7698 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7706 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7709 return TYPE_E_ELEMENTNOTFOUND
;
7712 /* internal function to make the inherited interfaces' methods appear
7713 * part of the interface */
7714 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7715 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7717 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7720 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7722 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7724 ITypeInfo
*pSubTypeInfo
;
7726 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7730 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7732 ITypeInfo_Release(pSubTypeInfo
);
7736 *hRefType
-= DISPATCH_HREF_OFFSET
;
7738 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7739 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7744 struct search_res_tlb_params
7750 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7752 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7753 static const WCHAR formatW
[] = {'\\','%','d',0};
7754 WCHAR szPath
[MAX_PATH
+1];
7755 ITypeLib
*pTLib
= NULL
;
7759 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7762 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7765 if (snprintfW(szPath
+ len
, ARRAY_SIZE(szPath
) - len
, formatW
, LOWORD(lpszName
)) < 0)
7768 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7771 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7772 if (IsEqualGUID(params
->guid
, impl
->guid
))
7774 params
->pTLib
= pTLib
;
7775 return FALSE
; /* stop enumeration */
7777 ITypeLib_Release(pTLib
);
7783 /* ITypeInfo::GetRefTypeInfo
7785 * If a type description references other type descriptions, it retrieves
7786 * the referenced type descriptions.
7788 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7791 ITypeInfo
**ppTInfo
)
7793 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7794 HRESULT result
= E_FAIL
;
7797 return E_INVALIDARG
;
7799 if ((INT
)hRefType
< 0) {
7800 ITypeInfoImpl
*pTypeInfoImpl
;
7802 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7803 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7804 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7805 return TYPE_E_ELEMENTNOTFOUND
;
7807 /* when we meet a DUAL typeinfo, we must create the alternate
7810 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7812 *pTypeInfoImpl
= *This
;
7813 pTypeInfoImpl
->ref
= 0;
7814 list_init(&pTypeInfoImpl
->custdata_list
);
7816 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7817 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7819 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7821 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7822 /* the AddRef implicitly adds a reference to the parent typelib, which
7823 * stops the copied data from being destroyed until the new typeinfo's
7824 * refcount goes to zero, but we need to signal to the new instance to
7825 * not free its data structures when it is destroyed */
7826 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7828 ITypeInfo_AddRef(*ppTInfo
);
7831 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7832 (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7834 HREFTYPE href_dispatch
= hRefType
;
7835 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7837 TLBRefType
*ref_type
;
7838 ITypeLib
*pTLib
= NULL
;
7841 if(!(hRefType
& 0x1)){
7842 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7844 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7847 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7848 ITypeInfo_AddRef(*ppTInfo
);
7854 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7856 if(ref_type
->reference
== (hRefType
& (~0x3)))
7859 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7861 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7865 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7867 TRACE("internal reference\n");
7868 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7870 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7871 TRACE("typeinfo in imported typelib that is already loaded\n");
7872 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7873 ITypeLib_AddRef(pTLib
);
7876 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
7877 struct search_res_tlb_params params
;
7880 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7882 /* Search in resource table */
7883 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
7884 params
.pTLib
= NULL
;
7885 EnumResourceNamesW(NULL
, TYPELIBW
, search_res_tlb
, (LONG_PTR
)¶ms
);
7886 pTLib
= params
.pTLib
;
7891 /* Search on disk */
7892 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7893 ref_type
->pImpTLInfo
->wVersionMajor
,
7894 ref_type
->pImpTLInfo
->wVersionMinor
,
7895 This
->pTypeLib
->syskind
,
7896 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7898 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7900 result
= LoadTypeLib(libnam
, &pTLib
);
7901 SysFreeString(libnam
);
7904 if(SUCCEEDED(result
)) {
7905 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7906 ITypeLib_AddRef(pTLib
);
7910 if(SUCCEEDED(result
)) {
7911 if(ref_type
->index
== TLB_REF_USE_GUID
)
7912 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7914 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7917 ITypeLib_Release(pTLib
);
7921 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7922 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7926 /* ITypeInfo::AddressOfMember
7928 * Retrieves the addresses of static functions or variables, such as those
7931 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7932 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7934 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7940 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7942 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7946 module
= LoadLibraryW(dll
);
7949 ERR("couldn't load %s\n", debugstr_w(dll
));
7951 SysFreeString(entry
);
7952 return STG_E_FILENOTFOUND
;
7954 /* FIXME: store library somewhere where we can free it */
7959 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7960 entryA
= heap_alloc(len
);
7961 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7963 *ppv
= GetProcAddress(module
, entryA
);
7965 ERR("function not found %s\n", debugstr_a(entryA
));
7971 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7973 ERR("function not found %d\n", ordinal
);
7977 SysFreeString(entry
);
7980 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7985 /* ITypeInfo::CreateInstance
7987 * Creates a new instance of a type that describes a component object class
7990 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7991 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7993 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7997 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
8003 WARN("Not able to aggregate\n");
8004 return CLASS_E_NOAGGREGATION
;
8007 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
8008 if(FAILED(hr
)) return hr
;
8010 if(pTA
->typekind
!= TKIND_COCLASS
)
8012 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
8018 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
8021 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
8022 TRACE("GetActiveObject rets %08x\n", hr
);
8025 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
8026 IUnknown_Release(pUnk
);
8031 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
8032 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8036 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8040 /* ITypeInfo::GetMops
8042 * Retrieves marshalling information.
8044 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
8047 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8048 FIXME("(%p %d) stub!\n", This
, memid
);
8053 /* ITypeInfo::GetContainingTypeLib
8055 * Retrieves the containing type library and the index of the type description
8056 * within that type library.
8058 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8059 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8061 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8063 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8065 *pIndex
=This
->index
;
8066 TRACE("returning pIndex=%d\n", *pIndex
);
8070 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8071 ITypeLib_AddRef(*ppTLib
);
8072 TRACE("returning ppTLib=%p\n", *ppTLib
);
8078 /* ITypeInfo::ReleaseTypeAttr
8080 * Releases a TYPEATTR previously returned by Get
8083 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8084 TYPEATTR
* pTypeAttr
)
8086 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8087 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8088 heap_free(pTypeAttr
);
8091 /* ITypeInfo::ReleaseFuncDesc
8093 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8095 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8097 FUNCDESC
*pFuncDesc
)
8099 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8102 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8104 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8105 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8106 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8108 SysFreeString((BSTR
)pFuncDesc
);
8111 /* ITypeInfo::ReleaseVarDesc
8113 * Releases a VARDESC previously returned by GetVarDesc.
8115 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8118 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8119 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8121 TLB_FreeVarDesc(pVarDesc
);
8124 /* ITypeInfo2::GetTypeKind
8126 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8129 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8130 TYPEKIND
*pTypeKind
)
8132 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8133 *pTypeKind
= This
->typeattr
.typekind
;
8134 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8138 /* ITypeInfo2::GetTypeFlags
8140 * Returns the type flags without any allocations. This returns a DWORD type
8141 * flag, which expands the type flags without growing the TYPEATTR (type
8145 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8147 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8148 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8149 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
8153 /* ITypeInfo2::GetFuncIndexOfMemId
8154 * Binds to a specific member based on a known DISPID, where the member name
8155 * is not known (for example, when binding to a default member).
8158 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8159 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8161 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8165 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8166 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8167 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8170 if(fdc
< This
->typeattr
.cFuncs
) {
8174 result
= TYPE_E_ELEMENTNOTFOUND
;
8176 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
8177 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8181 /* TypeInfo2::GetVarIndexOfMemId
8183 * Binds to a specific member based on a known DISPID, where the member name
8184 * is not known (for example, when binding to a default member).
8187 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8188 MEMBERID memid
, UINT
*pVarIndex
)
8190 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8191 TLBVarDesc
*pVarInfo
;
8193 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8195 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
8197 return TYPE_E_ELEMENTNOTFOUND
;
8199 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8204 /* ITypeInfo2::GetCustData
8206 * Gets the custom data
8208 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8213 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8214 TLBCustData
*pCData
;
8216 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8218 if(!guid
|| !pVarVal
)
8219 return E_INVALIDARG
;
8221 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8223 VariantInit( pVarVal
);
8225 VariantCopy( pVarVal
, &pCData
->data
);
8227 VariantClear( pVarVal
);
8231 /* ITypeInfo2::GetFuncCustData
8233 * Gets the custom data
8235 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8241 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8242 TLBCustData
*pCData
;
8243 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8245 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8247 if(index
>= This
->typeattr
.cFuncs
)
8248 return TYPE_E_ELEMENTNOTFOUND
;
8250 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8252 return TYPE_E_ELEMENTNOTFOUND
;
8254 VariantInit(pVarVal
);
8255 VariantCopy(pVarVal
, &pCData
->data
);
8260 /* ITypeInfo2::GetParamCustData
8262 * Gets the custom data
8264 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8271 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8272 TLBCustData
*pCData
;
8273 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8275 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8276 debugstr_guid(guid
), pVarVal
);
8278 if(indexFunc
>= This
->typeattr
.cFuncs
)
8279 return TYPE_E_ELEMENTNOTFOUND
;
8281 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8282 return TYPE_E_ELEMENTNOTFOUND
;
8284 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8286 return TYPE_E_ELEMENTNOTFOUND
;
8288 VariantInit(pVarVal
);
8289 VariantCopy(pVarVal
, &pCData
->data
);
8294 /* ITypeInfo2::GetVarCustData
8296 * Gets the custom data
8298 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8304 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8305 TLBCustData
*pCData
;
8306 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8308 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8310 if(index
>= This
->typeattr
.cVars
)
8311 return TYPE_E_ELEMENTNOTFOUND
;
8313 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8315 return TYPE_E_ELEMENTNOTFOUND
;
8317 VariantInit(pVarVal
);
8318 VariantCopy(pVarVal
, &pCData
->data
);
8323 /* ITypeInfo2::GetImplCustData
8325 * Gets the custom data
8327 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8333 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8334 TLBCustData
*pCData
;
8335 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8337 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8339 if(index
>= This
->typeattr
.cImplTypes
)
8340 return TYPE_E_ELEMENTNOTFOUND
;
8342 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8344 return TYPE_E_ELEMENTNOTFOUND
;
8346 VariantInit(pVarVal
);
8347 VariantCopy(pVarVal
, &pCData
->data
);
8352 /* ITypeInfo2::GetDocumentation2
8354 * Retrieves the documentation string, the complete Help file name and path,
8355 * the localization context to use, and the context ID for the library Help
8356 * topic in the Help file.
8359 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8363 BSTR
*pbstrHelpString
,
8364 DWORD
*pdwHelpStringContext
,
8365 BSTR
*pbstrHelpStringDll
)
8367 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8368 const TLBFuncDesc
*pFDesc
;
8369 const TLBVarDesc
*pVDesc
;
8370 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8371 "HelpStringContext(%p) HelpStringDll(%p)\n",
8372 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8373 pbstrHelpStringDll
);
8374 /* the help string should be obtained from the helpstringdll,
8375 * using the _DLLGetDocumentation function, based on the supplied
8376 * lcid. Nice to do sometime...
8378 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8380 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8381 if(pdwHelpStringContext
)
8382 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8383 if(pbstrHelpStringDll
)
8384 *pbstrHelpStringDll
=
8385 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8387 }else {/* for a member */
8388 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
8391 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8392 if(pdwHelpStringContext
)
8393 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8394 if(pbstrHelpStringDll
)
8395 *pbstrHelpStringDll
=
8396 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8399 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
8402 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8403 if(pdwHelpStringContext
)
8404 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8405 if(pbstrHelpStringDll
)
8406 *pbstrHelpStringDll
=
8407 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8411 return TYPE_E_ELEMENTNOTFOUND
;
8414 /* ITypeInfo2::GetAllCustData
8416 * Gets all custom data items for the Type info.
8419 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8421 CUSTDATA
*pCustData
)
8423 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8425 TRACE("%p %p\n", This
, pCustData
);
8427 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8430 /* ITypeInfo2::GetAllFuncCustData
8432 * Gets all custom data items for the specified Function
8435 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8438 CUSTDATA
*pCustData
)
8440 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8441 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8443 TRACE("%p %u %p\n", This
, index
, pCustData
);
8445 if(index
>= This
->typeattr
.cFuncs
)
8446 return TYPE_E_ELEMENTNOTFOUND
;
8448 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8451 /* ITypeInfo2::GetAllParamCustData
8453 * Gets all custom data items for the Functions
8456 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8457 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8459 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8460 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8462 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8464 if(indexFunc
>= This
->typeattr
.cFuncs
)
8465 return TYPE_E_ELEMENTNOTFOUND
;
8467 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8468 return TYPE_E_ELEMENTNOTFOUND
;
8470 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8473 /* ITypeInfo2::GetAllVarCustData
8475 * Gets all custom data items for the specified Variable
8478 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8479 UINT index
, CUSTDATA
*pCustData
)
8481 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8482 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8484 TRACE("%p %u %p\n", This
, index
, pCustData
);
8486 if(index
>= This
->typeattr
.cVars
)
8487 return TYPE_E_ELEMENTNOTFOUND
;
8489 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8492 /* ITypeInfo2::GetAllImplCustData
8494 * Gets all custom data items for the specified implementation type
8497 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8500 CUSTDATA
*pCustData
)
8502 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8503 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8505 TRACE("%p %u %p\n", This
, index
, pCustData
);
8507 if(index
>= This
->typeattr
.cImplTypes
)
8508 return TYPE_E_ELEMENTNOTFOUND
;
8510 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8513 static const ITypeInfo2Vtbl tinfvt
=
8516 ITypeInfo_fnQueryInterface
,
8518 ITypeInfo_fnRelease
,
8520 ITypeInfo_fnGetTypeAttr
,
8521 ITypeInfo_fnGetTypeComp
,
8522 ITypeInfo_fnGetFuncDesc
,
8523 ITypeInfo_fnGetVarDesc
,
8524 ITypeInfo_fnGetNames
,
8525 ITypeInfo_fnGetRefTypeOfImplType
,
8526 ITypeInfo_fnGetImplTypeFlags
,
8527 ITypeInfo_fnGetIDsOfNames
,
8529 ITypeInfo_fnGetDocumentation
,
8530 ITypeInfo_fnGetDllEntry
,
8531 ITypeInfo_fnGetRefTypeInfo
,
8532 ITypeInfo_fnAddressOfMember
,
8533 ITypeInfo_fnCreateInstance
,
8534 ITypeInfo_fnGetMops
,
8535 ITypeInfo_fnGetContainingTypeLib
,
8536 ITypeInfo_fnReleaseTypeAttr
,
8537 ITypeInfo_fnReleaseFuncDesc
,
8538 ITypeInfo_fnReleaseVarDesc
,
8540 ITypeInfo2_fnGetTypeKind
,
8541 ITypeInfo2_fnGetTypeFlags
,
8542 ITypeInfo2_fnGetFuncIndexOfMemId
,
8543 ITypeInfo2_fnGetVarIndexOfMemId
,
8544 ITypeInfo2_fnGetCustData
,
8545 ITypeInfo2_fnGetFuncCustData
,
8546 ITypeInfo2_fnGetParamCustData
,
8547 ITypeInfo2_fnGetVarCustData
,
8548 ITypeInfo2_fnGetImplTypeCustData
,
8549 ITypeInfo2_fnGetDocumentation2
,
8550 ITypeInfo2_fnGetAllCustData
,
8551 ITypeInfo2_fnGetAllFuncCustData
,
8552 ITypeInfo2_fnGetAllParamCustData
,
8553 ITypeInfo2_fnGetAllVarCustData
,
8554 ITypeInfo2_fnGetAllImplTypeCustData
,
8557 /******************************************************************************
8558 * CreateDispTypeInfo [OLEAUT32.31]
8560 * Build type information for an object so it can be called through an
8561 * IDispatch interface.
8564 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8565 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8568 * This call allows an objects methods to be accessed through IDispatch, by
8569 * building an ITypeInfo object that IDispatch can use to call through.
8571 HRESULT WINAPI
CreateDispTypeInfo(
8572 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8573 LCID lcid
, /* [I] Locale Id */
8574 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8576 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8577 ITypeLibImpl
*pTypeLibImpl
;
8578 unsigned int param
, func
;
8579 TLBFuncDesc
*pFuncDesc
;
8583 pTypeLibImpl
= TypeLibImpl_Constructor();
8584 if (!pTypeLibImpl
) return E_FAIL
;
8586 pTypeLibImpl
->TypeInfoCount
= 2;
8587 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8589 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8590 pTIIface
->pTypeLib
= pTypeLibImpl
;
8591 pTIIface
->index
= 0;
8592 pTIIface
->Name
= NULL
;
8593 pTIIface
->dwHelpContext
= -1;
8594 pTIIface
->guid
= NULL
;
8595 pTIIface
->typeattr
.lcid
= lcid
;
8596 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8597 pTIIface
->typeattr
.wMajorVerNum
= 0;
8598 pTIIface
->typeattr
.wMinorVerNum
= 0;
8599 pTIIface
->typeattr
.cbAlignment
= 2;
8600 pTIIface
->typeattr
.cbSizeInstance
= -1;
8601 pTIIface
->typeattr
.cbSizeVft
= -1;
8602 pTIIface
->typeattr
.cFuncs
= 0;
8603 pTIIface
->typeattr
.cImplTypes
= 0;
8604 pTIIface
->typeattr
.cVars
= 0;
8605 pTIIface
->typeattr
.wTypeFlags
= 0;
8606 pTIIface
->hreftype
= 0;
8608 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8609 pFuncDesc
= pTIIface
->funcdescs
;
8610 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8611 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8612 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8613 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8614 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8615 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8616 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8617 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8618 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8619 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8620 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8621 pFuncDesc
->funcdesc
.cScodes
= 0;
8622 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8623 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8624 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8625 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8626 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8627 md
->cArgs
* sizeof(ELEMDESC
));
8628 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8629 for(param
= 0; param
< md
->cArgs
; param
++) {
8630 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8631 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8633 pFuncDesc
->helpcontext
= 0;
8634 pFuncDesc
->HelpStringContext
= 0;
8635 pFuncDesc
->HelpString
= NULL
;
8636 pFuncDesc
->Entry
= NULL
;
8637 list_init(&pFuncDesc
->custdata_list
);
8638 pTIIface
->typeattr
.cFuncs
++;
8642 dump_TypeInfo(pTIIface
);
8644 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8645 pTIClass
->pTypeLib
= pTypeLibImpl
;
8646 pTIClass
->index
= 1;
8647 pTIClass
->Name
= NULL
;
8648 pTIClass
->dwHelpContext
= -1;
8649 pTIClass
->guid
= NULL
;
8650 pTIClass
->typeattr
.lcid
= lcid
;
8651 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8652 pTIClass
->typeattr
.wMajorVerNum
= 0;
8653 pTIClass
->typeattr
.wMinorVerNum
= 0;
8654 pTIClass
->typeattr
.cbAlignment
= 2;
8655 pTIClass
->typeattr
.cbSizeInstance
= -1;
8656 pTIClass
->typeattr
.cbSizeVft
= -1;
8657 pTIClass
->typeattr
.cFuncs
= 0;
8658 pTIClass
->typeattr
.cImplTypes
= 1;
8659 pTIClass
->typeattr
.cVars
= 0;
8660 pTIClass
->typeattr
.wTypeFlags
= 0;
8661 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8663 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8665 ref
= heap_alloc_zero(sizeof(*ref
));
8666 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8667 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8669 dump_TypeInfo(pTIClass
);
8671 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8673 ITypeInfo_AddRef(*pptinfo
);
8674 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8680 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8682 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8684 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8687 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8689 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8691 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8694 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8696 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8698 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8701 static HRESULT WINAPI
ITypeComp_fnBind(
8706 ITypeInfo
** ppTInfo
,
8707 DESCKIND
* pDescKind
,
8710 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8711 const TLBFuncDesc
*pFDesc
;
8712 const TLBVarDesc
*pVDesc
;
8713 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8716 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8718 *pDescKind
= DESCKIND_NONE
;
8719 pBindPtr
->lpfuncdesc
= NULL
;
8722 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8723 pFDesc
= &This
->funcdescs
[fdc
];
8724 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8725 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8728 /* name found, but wrong flags */
8729 hr
= TYPE_E_TYPEMISMATCH
;
8733 if (fdc
< This
->typeattr
.cFuncs
)
8735 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8737 &pBindPtr
->lpfuncdesc
,
8738 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8741 *pDescKind
= DESCKIND_FUNCDESC
;
8742 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8743 ITypeInfo_AddRef(*ppTInfo
);
8746 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, szName
);
8748 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8751 *pDescKind
= DESCKIND_VARDESC
;
8752 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8753 ITypeInfo_AddRef(*ppTInfo
);
8758 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8759 /* recursive search */
8763 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8766 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8767 ITypeInfo_Release(pTInfo
);
8771 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8772 ITypeComp_Release(pTComp
);
8773 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8774 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8776 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8777 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8778 SysFreeString((BSTR
)tmp
);
8782 WARN("Could not search inherited interface!\n");
8784 if (hr
== DISP_E_MEMBERNOTFOUND
)
8786 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8790 static HRESULT WINAPI
ITypeComp_fnBindType(
8794 ITypeInfo
** ppTInfo
,
8795 ITypeComp
** ppTComp
)
8797 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8799 /* strange behaviour (does nothing) but like the
8802 if (!ppTInfo
|| !ppTComp
)
8811 static const ITypeCompVtbl tcompvt
=
8814 ITypeComp_fnQueryInterface
,
8816 ITypeComp_fnRelease
,
8819 ITypeComp_fnBindType
8822 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8823 ICreateTypeLib2
** ppctlib
)
8828 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8830 if (!szFile
) return E_INVALIDARG
;
8832 This
= TypeLibImpl_Constructor();
8834 return E_OUTOFMEMORY
;
8836 This
->lcid
= GetSystemDefaultLCID();
8837 This
->syskind
= syskind
;
8838 This
->ptr_size
= get_ptr_size(syskind
);
8840 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8842 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8843 return E_OUTOFMEMORY
;
8845 lstrcpyW(This
->path
, szFile
);
8847 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8848 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8852 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8853 REFIID riid
, void **object
)
8855 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8857 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8860 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8862 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8864 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8867 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8869 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8871 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8874 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8875 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8877 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8878 ITypeInfoImpl
*info
;
8881 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8883 if (!ctinfo
|| !name
)
8884 return E_INVALIDARG
;
8886 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8888 return TYPE_E_NAMECONFLICT
;
8890 if (This
->typeinfos
)
8891 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8892 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8894 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8896 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8898 info
->pTypeLib
= This
;
8899 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8900 info
->index
= This
->TypeInfoCount
;
8901 info
->typeattr
.typekind
= kind
;
8902 info
->typeattr
.cbAlignment
= 4;
8904 switch (info
->typeattr
.typekind
) {
8906 case TKIND_INTERFACE
:
8907 case TKIND_DISPATCH
:
8909 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
8913 info
->typeattr
.cbSizeInstance
= 0;
8916 info
->typeattr
.cbSizeInstance
= 2;
8919 info
->typeattr
.cbSizeInstance
= -0x75;
8922 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
8923 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
8927 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8928 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8930 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8934 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8936 ++This
->TypeInfoCount
;
8941 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8944 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8946 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8949 return E_INVALIDARG
;
8951 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8956 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8957 WORD majorVerNum
, WORD minorVerNum
)
8959 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8961 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8963 This
->ver_major
= majorVerNum
;
8964 This
->ver_minor
= minorVerNum
;
8969 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8972 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8974 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8976 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8981 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8984 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8986 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8989 return E_INVALIDARG
;
8991 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8996 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8997 LPOLESTR helpFileName
)
8999 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9001 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
9004 return E_INVALIDARG
;
9006 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
9011 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
9014 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9016 TRACE("%p %d\n", This
, helpContext
);
9018 This
->dwHelpContext
= helpContext
;
9023 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
9026 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9028 TRACE("%p %x\n", This
, lcid
);
9030 This
->set_lcid
= lcid
;
9035 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9038 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9040 TRACE("%p %x\n", This
, libFlags
);
9042 This
->libflags
= libFlags
;
9047 typedef struct tagWMSFT_SegContents
{
9050 } WMSFT_SegContents
;
9052 typedef struct tagWMSFT_TLBFile
{
9054 WMSFT_SegContents typeinfo_seg
;
9055 WMSFT_SegContents impfile_seg
;
9056 WMSFT_SegContents impinfo_seg
;
9057 WMSFT_SegContents ref_seg
;
9058 WMSFT_SegContents guidhash_seg
;
9059 WMSFT_SegContents guid_seg
;
9060 WMSFT_SegContents namehash_seg
;
9061 WMSFT_SegContents name_seg
;
9062 WMSFT_SegContents string_seg
;
9063 WMSFT_SegContents typdesc_seg
;
9064 WMSFT_SegContents arraydesc_seg
;
9065 WMSFT_SegContents custdata_seg
;
9066 WMSFT_SegContents cdguids_seg
;
9068 WMSFT_SegContents aux_seg
;
9071 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9072 WMSFT_TLBFile
*file
)
9078 file
->string_seg
.len
= 0;
9079 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9082 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9084 return E_UNEXPECTED
;
9086 size
+= sizeof(INT16
);
9088 size
= (size
+ 4) & ~0x3;
9092 file
->string_seg
.len
+= size
;
9094 /* temporarily use str->offset to store the length of the aligned,
9095 * converted string */
9099 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
9102 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9105 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
9106 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9108 heap_free(file
->string_seg
.data
);
9109 return E_UNEXPECTED
;
9112 *((INT16
*)data
) = size
;
9114 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9118 str
->offset
= last_offs
;
9125 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9126 WMSFT_TLBFile
*file
)
9131 MSFT_NameIntro
*last_intro
= NULL
;
9133 file
->header
.nametablecount
= 0;
9134 file
->header
.nametablechars
= 0;
9136 file
->name_seg
.len
= 0;
9137 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9140 size
= strlenW(str
->str
);
9141 file
->header
.nametablechars
+= size
;
9142 file
->header
.nametablecount
++;
9144 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9146 return E_UNEXPECTED
;
9148 size
+= sizeof(MSFT_NameIntro
);
9150 size
= (size
+ 4) & ~0x3;
9154 file
->name_seg
.len
+= size
;
9156 /* temporarily use str->offset to store the length of the aligned,
9157 * converted string */
9161 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9162 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
9165 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9167 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9169 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
9170 data
+ sizeof(MSFT_NameIntro
),
9171 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9173 heap_free(file
->name_seg
.data
);
9174 return E_UNEXPECTED
;
9176 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9178 intro
->hreftype
= -1; /* TODO? */
9179 intro
->namelen
= size
& 0xFF;
9180 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9181 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9182 intro
->namelen
|= hash
<< 16;
9183 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9184 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9186 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9187 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9189 /* update str->offset to actual value to use in other
9190 * compilation functions that require positions within
9191 * the string table */
9195 str
->offset
= last_offs
;
9200 last_intro
->hreftype
= 0; /* last one is 0? */
9205 static inline int hash_guid(GUID
*guid
)
9209 for (i
= 0; i
< 8; i
++)
9210 hash
^= ((const short *)guid
)[i
];
9215 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9218 MSFT_GuidEntry
*entry
;
9220 int hash_key
, *guidhashtab
;
9222 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9223 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9225 entry
= file
->guid_seg
.data
;
9227 guidhashtab
= file
->guidhash_seg
.data
;
9228 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9229 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9230 entry
->hreftype
= guid
->hreftype
;
9232 hash_key
= hash_guid(&guid
->guid
);
9233 entry
->next_hash
= guidhashtab
[hash_key
];
9234 guidhashtab
[hash_key
] = offs
;
9236 guid
->offset
= offs
;
9237 offs
+= sizeof(MSFT_GuidEntry
);
9244 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9247 VARTYPE arg_type
= V_VT(value
);
9250 DWORD ret
= file
->custdata_seg
.len
;
9252 if(arg_type
== VT_INT
)
9254 if(arg_type
== VT_UINT
)
9258 if(V_VT(value
) != arg_type
) {
9259 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9261 ERR("VariantChangeType failed: %08x\n", hres
);
9266 /* Check if default value can be stored in-place */
9271 if(V_UI4(&v
) > 0x3ffffff)
9284 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9287 /* have to allocate space in custdata_seg */
9296 /* Construct the data to be allocated */
9299 if(file
->custdata_seg
.data
){
9300 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9301 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9302 file
->custdata_seg
.len
+= sizeof(int) * 2;
9304 file
->custdata_seg
.len
= sizeof(int) * 2;
9305 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9308 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9309 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9311 /* TODO: Check if the encoded data is already present in custdata_seg */
9317 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9320 if(file
->custdata_seg
.data
){
9321 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9322 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9323 file
->custdata_seg
.len
+= len
;
9325 file
->custdata_seg
.len
= len
;
9326 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9329 *((unsigned short *)data
) = V_VT(value
);
9330 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9331 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9332 if(V_BSTR(&v
)[i
] <= 0x7f)
9333 data
[i
+6] = V_BSTR(&v
)[i
];
9337 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9338 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9341 /* TODO: Check if the encoded data is already present in custdata_seg */
9346 FIXME("Argument type not yet handled\n");
9351 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9353 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9355 DWORD offs
= file
->arraydesc_seg
.len
;
9359 /* TODO: we should check for duplicates, but that's harder because each
9360 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9361 * at the library-level) */
9363 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9364 if(!file
->arraydesc_seg
.data
)
9365 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9367 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9368 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9370 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9371 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9372 for(i
= 0; i
< desc
->cDims
; ++i
){
9373 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9374 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9380 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9386 VARTYPE vt
, subtype
;
9397 vt
= desc
->vt
& VT_TYPEMASK
;
9399 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9401 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9402 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9404 *out_size
+= 2 * sizeof(DWORD
);
9405 }else if(vt
== VT_CARRAY
){
9406 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9407 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9409 }else if(vt
== VT_USERDEFINED
){
9410 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9411 encoded
[1] = desc
->u
.hreftype
;
9412 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9414 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9432 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9435 data
= file
->typdesc_seg
.data
;
9436 while(offs
< file
->typdesc_seg
.len
){
9437 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9439 offs
+= sizeof(encoded
);
9442 file
->typdesc_seg
.len
+= sizeof(encoded
);
9443 if(!file
->typdesc_seg
.data
)
9444 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9446 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9448 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9453 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9455 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9456 DWORD ret
= cdguids_seg
->len
, offs
;
9457 MSFT_CDGuid
*cdguid
;
9460 if(list_empty(custdata_list
))
9463 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9464 if(!cdguids_seg
->data
){
9465 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9467 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9468 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9471 offs
= ret
+ sizeof(MSFT_CDGuid
);
9472 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9473 cdguid
->GuidOffset
= cd
->guid
->offset
;
9474 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9475 cdguid
->next
= offs
;
9476 offs
+= sizeof(MSFT_CDGuid
);
9486 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9487 WMSFT_TLBFile
*file
)
9489 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9490 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9491 MSFT_VarRecord
*varrecord
;
9492 MSFT_FuncRecord
*funcrecord
;
9494 DWORD
*name
, *offsets
, offs
;
9496 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9497 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9499 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9501 /* optional fields */
9502 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9503 if(!list_empty(&desc
->custdata_list
))
9504 recorded_size
+= 7 * sizeof(INT
);
9505 else if(desc
->HelpStringContext
!= 0)
9506 recorded_size
+= 6 * sizeof(INT
);
9508 else if(desc
->Entry
)
9509 recorded_size
+= 3 * sizeof(INT
);
9510 else if(desc
->HelpString
)
9511 recorded_size
+= 2 * sizeof(INT
);
9512 else if(desc
->helpcontext
)
9513 recorded_size
+= sizeof(INT
);
9515 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9517 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9518 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9519 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9524 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9527 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9528 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9530 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9532 /* optional fields */
9533 if(desc
->HelpStringContext
!= 0)
9534 recorded_size
+= 5 * sizeof(INT
);
9535 else if(!list_empty(&desc
->custdata_list
))
9536 recorded_size
+= 4 * sizeof(INT
);
9538 else if(desc
->HelpString
)
9539 recorded_size
+= 2 * sizeof(INT
);
9540 else if(desc
->HelpContext
!= 0)
9541 recorded_size
+= sizeof(INT
);
9543 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9546 if(!recorded_size
&& !extra_size
)
9549 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9551 aux_seg
->len
+= recorded_size
+ extra_size
;
9553 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9556 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9558 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9560 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9562 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9565 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9566 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9567 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9568 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9570 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9571 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9572 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9573 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9576 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9581 * ^has_param_defaults
9582 * ^oEntry_is_intresource
9584 funcrecord
->FKCCIC
=
9585 desc
->funcdesc
.funckind
|
9586 (desc
->funcdesc
.invkind
<< 3) |
9587 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9588 (desc
->funcdesc
.callconv
<< 8);
9590 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9591 funcrecord
->FKCCIC
|= 0x2000;
9593 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9594 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9595 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9596 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9599 if(paramdefault_size
> 0)
9600 funcrecord
->FKCCIC
|= 0x1000;
9602 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9603 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9605 /* optional fields */
9607 if(!list_empty(&desc
->custdata_list
)){
9608 size
+= 7 * sizeof(INT
);
9609 funcrecord
->HelpContext
= desc
->helpcontext
;
9610 if(desc
->HelpString
)
9611 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9613 funcrecord
->oHelpString
= -1;
9615 funcrecord
->oEntry
= -1;
9616 else if(IS_INTRESOURCE(desc
->Entry
))
9617 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9619 funcrecord
->oEntry
= desc
->Entry
->offset
;
9620 funcrecord
->res9
= -1;
9621 funcrecord
->resA
= -1;
9622 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9623 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9624 }else if(desc
->HelpStringContext
!= 0){
9625 size
+= 6 * sizeof(INT
);
9626 funcrecord
->HelpContext
= desc
->helpcontext
;
9627 if(desc
->HelpString
)
9628 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9630 funcrecord
->oHelpString
= -1;
9632 funcrecord
->oEntry
= -1;
9633 else if(IS_INTRESOURCE(desc
->Entry
))
9634 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9636 funcrecord
->oEntry
= desc
->Entry
->offset
;
9637 funcrecord
->res9
= -1;
9638 funcrecord
->resA
= -1;
9639 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9640 }else if(desc
->Entry
){
9641 size
+= 3 * sizeof(INT
);
9642 funcrecord
->HelpContext
= desc
->helpcontext
;
9643 if(desc
->HelpString
)
9644 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9646 funcrecord
->oHelpString
= -1;
9648 funcrecord
->oEntry
= -1;
9649 else if(IS_INTRESOURCE(desc
->Entry
))
9650 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9652 funcrecord
->oEntry
= desc
->Entry
->offset
;
9653 }else if(desc
->HelpString
){
9654 size
+= 2 * sizeof(INT
);
9655 funcrecord
->HelpContext
= desc
->helpcontext
;
9656 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9657 }else if(desc
->helpcontext
){
9658 size
+= sizeof(INT
);
9659 funcrecord
->HelpContext
= desc
->helpcontext
;
9662 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9663 size
+= paramdefault_size
;
9665 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9666 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9668 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9669 if(desc
->pParamDesc
[j
].Name
)
9670 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9673 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9675 if(paramdefault_size
){
9676 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9677 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9678 else if(paramdefault_size
)
9683 size
+= sizeof(MSFT_ParameterInfo
);
9686 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9692 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9695 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9696 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9697 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9698 DWORD size
= 5 * sizeof(INT
);
9700 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9701 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9702 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9703 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9705 if(desc
->vardesc
.varkind
== VAR_CONST
){
9706 varrecord
->vardescsize
+= sizeof(VARIANT
);
9707 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9709 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9712 if(desc
->HelpStringContext
!= 0){
9713 size
+= 5 * sizeof(INT
);
9714 varrecord
->HelpContext
= desc
->HelpContext
;
9715 if(desc
->HelpString
)
9716 varrecord
->HelpString
= desc
->HelpString
->offset
;
9718 varrecord
->HelpString
= -1;
9719 varrecord
->res9
= -1;
9720 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9721 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9722 }else if(!list_empty(&desc
->custdata_list
)){
9723 size
+= 4 * sizeof(INT
);
9724 varrecord
->HelpContext
= desc
->HelpContext
;
9725 if(desc
->HelpString
)
9726 varrecord
->HelpString
= desc
->HelpString
->offset
;
9728 varrecord
->HelpString
= -1;
9729 varrecord
->res9
= -1;
9730 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9731 }else if(desc
->HelpString
){
9732 size
+= 2 * sizeof(INT
);
9733 varrecord
->HelpContext
= desc
->HelpContext
;
9734 if(desc
->HelpString
)
9735 varrecord
->HelpString
= desc
->HelpString
->offset
;
9737 varrecord
->HelpString
= -1;
9738 }else if(desc
->HelpContext
!= 0){
9739 size
+= sizeof(INT
);
9740 varrecord
->HelpContext
= desc
->HelpContext
;
9743 varrecord
->Info
= size
| (i
<< 16);
9749 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9752 memid
= (MEMBERID
*)varrecord
;
9753 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9754 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9755 *memid
= desc
->funcdesc
.memid
;
9758 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9759 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9760 *memid
= desc
->vardesc
.memid
;
9764 name
= (UINT
*)memid
;
9765 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9766 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9768 *name
= desc
->Name
->offset
;
9773 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9774 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9776 *name
= desc
->Name
->offset
;
9785 typedef struct tagWMSFT_RefChunk
{
9792 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9794 DWORD offs
= file
->ref_seg
.len
, i
;
9795 WMSFT_RefChunk
*chunk
;
9797 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9798 if(!file
->ref_seg
.data
)
9799 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9801 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9803 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9805 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9806 chunk
->href
= info
->impltypes
[i
].hRef
;
9807 chunk
->res04
= info
->impltypes
[i
].implflags
;
9809 if(i
< info
->typeattr
.cImplTypes
- 1)
9810 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9819 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9823 size
= sizeof(MSFT_TypeInfoBase
);
9826 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9827 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9828 base
->typekind
= TKIND_DISPATCH
;
9830 base
->typekind
= info
->typeattr
.typekind
;
9831 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9832 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
9833 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9838 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
9844 base
->posguid
= info
->guid
->offset
;
9847 base
->flags
= info
->typeattr
.wTypeFlags
;
9849 base
->NameOffset
= info
->Name
->offset
;
9851 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9852 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9854 base
->NameOffset
= -1;
9856 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
9858 base
->docstringoffs
= info
->DocString
->offset
;
9860 base
->docstringoffs
= -1;
9861 base
->helpstringcontext
= info
->dwHelpStringContext
;
9862 base
->helpcontext
= info
->dwHelpContext
;
9863 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9864 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
9865 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
9866 base
->size
= info
->typeattr
.cbSizeInstance
;
9867 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
9868 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9869 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
9870 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9871 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
9873 base
->datatype1
= info
->DllName
->offset
;
9875 base
->datatype1
= -1;
9877 if(info
->typeattr
.cImplTypes
> 0)
9878 base
->datatype1
= info
->impltypes
[0].hRef
;
9880 base
->datatype1
= -1;
9882 base
->datatype2
= index
; /* FIXME: i think there's more here */
9890 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9894 file
->typeinfo_seg
.len
= 0;
9895 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9896 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9897 *junk
= file
->typeinfo_seg
.len
;
9899 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9902 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9903 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9905 file
->aux_seg
.len
= 0;
9906 file
->aux_seg
.data
= NULL
;
9908 file
->typeinfo_seg
.len
= 0;
9909 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9910 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9911 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9912 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9916 typedef struct tagWMSFT_ImpFile
{
9922 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9925 WMSFT_ImpFile
*impfile
;
9927 DWORD last_offs
= 0;
9929 file
->impfile_seg
.len
= 0;
9930 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9934 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9938 path
= implib
->name
;
9939 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9941 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9944 size
+= sizeof(INT16
);
9946 size
= (size
+ 4) & ~0x3;
9950 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9953 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9955 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9956 int strlen
= 0, size
;
9958 impfile
= (WMSFT_ImpFile
*)data
;
9959 impfile
->guid_offs
= implib
->guid
->offset
;
9960 impfile
->lcid
= implib
->lcid
;
9961 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9963 data
+= sizeof(WMSFT_ImpFile
);
9966 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9970 path
= implib
->name
;
9971 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9972 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9974 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9977 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9979 size
= strlen
+ sizeof(INT16
);
9981 size
= (size
+ 4) & ~0x3;
9984 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9987 implib
->offset
= last_offs
;
9988 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9992 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9995 TLBRefType
*ref_type
;
9998 WMSFT_compile_impfile(This
, file
);
10000 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
10001 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
10003 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
10004 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
10005 if(ref_type
->index
== TLB_REF_USE_GUID
){
10006 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
10007 info
->oGuid
= ref_type
->guid
->offset
;
10009 info
->oGuid
= ref_type
->index
;
10010 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
10016 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10018 file
->guidhash_seg
.len
= 0x80;
10019 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
10020 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
10023 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10025 file
->namehash_seg
.len
= 0x200;
10026 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
10027 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
10030 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
10032 if(contents
&& contents
->len
){
10033 segdir
->offset
= *running_offset
;
10034 segdir
->length
= contents
->len
;
10035 *running_offset
+= segdir
->length
;
10037 segdir
->offset
= -1;
10038 segdir
->length
= 0;
10041 /* TODO: do these ever change? */
10042 segdir
->res08
= -1;
10043 segdir
->res0c
= 0xf;
10046 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10050 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10053 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10057 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10059 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10060 base
->memoffset
+= file_len
;
10067 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10069 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
10070 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
10071 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
10072 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
10073 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
10074 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
10075 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
10076 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
10077 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
10078 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
10079 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
10080 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
10081 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
10082 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
10085 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10087 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10088 WMSFT_TLBFile file
;
10089 DWORD written
, junk_size
, junk_offs
, running_offset
;
10096 TRACE("%p\n", This
);
10098 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10099 if(This
->typeinfos
[i
]->needs_layout
)
10100 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10102 memset(&file
, 0, sizeof(file
));
10104 file
.header
.magic1
= 0x5446534D;
10105 file
.header
.magic2
= 0x00010002;
10106 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10107 file
.header
.lcid2
= This
->set_lcid
;
10108 file
.header
.varflags
= 0x40 | This
->syskind
;
10109 if (This
->HelpFile
)
10110 file
.header
.varflags
|= 0x10;
10111 if (This
->HelpStringDll
)
10112 file
.header
.varflags
|= HELPDLLFLAG
;
10113 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10114 file
.header
.flags
= This
->libflags
;
10115 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10116 file
.header
.helpcontext
= This
->dwHelpContext
;
10117 file
.header
.res44
= 0x20;
10118 file
.header
.res48
= 0x80;
10119 file
.header
.dispatchpos
= This
->dispatch_href
;
10121 WMSFT_compile_namehash(This
, &file
);
10122 /* do name and string compilation to get offsets for other compilations */
10123 hres
= WMSFT_compile_names(This
, &file
);
10125 WMSFT_free_file(&file
);
10129 hres
= WMSFT_compile_strings(This
, &file
);
10131 WMSFT_free_file(&file
);
10135 WMSFT_compile_guidhash(This
, &file
);
10136 hres
= WMSFT_compile_guids(This
, &file
);
10138 WMSFT_free_file(&file
);
10143 file
.header
.helpfile
= This
->HelpFile
->offset
;
10145 file
.header
.helpfile
= -1;
10147 if(This
->DocString
)
10148 file
.header
.helpstring
= This
->DocString
->offset
;
10150 file
.header
.helpstring
= -1;
10152 /* do some more segment compilation */
10153 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10154 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10157 file
.header
.NameOffset
= This
->Name
->offset
;
10159 file
.header
.NameOffset
= -1;
10161 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10164 file
.header
.posguid
= This
->guid
->offset
;
10166 file
.header
.posguid
= -1;
10168 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10169 if(file
.header
.varflags
& HELPDLLFLAG
)
10170 junk_size
+= sizeof(DWORD
);
10172 junk
= heap_alloc_zero(junk_size
);
10173 if(file
.header
.varflags
& HELPDLLFLAG
){
10174 *junk
= This
->HelpStringDll
->offset
;
10183 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10184 WMSFT_compile_impinfo(This
, &file
);
10186 running_offset
= 0;
10188 TRACE("header at: 0x%x\n", running_offset
);
10189 running_offset
+= sizeof(file
.header
);
10191 TRACE("junk at: 0x%x\n", running_offset
);
10192 running_offset
+= junk_size
;
10194 TRACE("segdir at: 0x%x\n", running_offset
);
10195 running_offset
+= sizeof(file
.segdir
);
10197 TRACE("typeinfo at: 0x%x\n", running_offset
);
10198 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10200 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10201 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10203 TRACE("guidtab at: 0x%x\n", running_offset
);
10204 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10206 TRACE("reftab at: 0x%x\n", running_offset
);
10207 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10209 TRACE("impinfo at: 0x%x\n", running_offset
);
10210 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10212 TRACE("impfiles at: 0x%x\n", running_offset
);
10213 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10215 TRACE("namehashtab at: 0x%x\n", running_offset
);
10216 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10218 TRACE("nametab at: 0x%x\n", running_offset
);
10219 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10221 TRACE("stringtab at: 0x%x\n", running_offset
);
10222 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10224 TRACE("typdesc at: 0x%x\n", running_offset
);
10225 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10227 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10228 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10230 TRACE("custdata at: 0x%x\n", running_offset
);
10231 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10233 TRACE("cdguids at: 0x%x\n", running_offset
);
10234 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10236 TRACE("res0e at: 0x%x\n", running_offset
);
10237 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10239 TRACE("res0f at: 0x%x\n", running_offset
);
10240 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10242 TRACE("aux_seg at: 0x%x\n", running_offset
);
10244 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10246 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10247 FILE_ATTRIBUTE_NORMAL
, 0);
10248 if (outfile
== INVALID_HANDLE_VALUE
){
10249 WMSFT_free_file(&file
);
10251 return TYPE_E_IOERROR
;
10254 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10256 WMSFT_free_file(&file
);
10257 CloseHandle(outfile
);
10259 return TYPE_E_IOERROR
;
10262 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10265 WMSFT_free_file(&file
);
10266 CloseHandle(outfile
);
10267 return TYPE_E_IOERROR
;
10270 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10272 WMSFT_free_file(&file
);
10273 CloseHandle(outfile
);
10274 return TYPE_E_IOERROR
;
10277 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10278 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10279 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10280 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10281 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10282 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10283 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10284 WMSFT_write_segment(outfile
, &file
.name_seg
);
10285 WMSFT_write_segment(outfile
, &file
.string_seg
);
10286 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10287 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10288 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10289 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10290 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10292 WMSFT_free_file(&file
);
10294 CloseHandle(outfile
);
10299 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10302 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10303 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10307 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10308 REFGUID guid
, VARIANT
*varVal
)
10310 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10313 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10315 if (!guid
|| !varVal
)
10316 return E_INVALIDARG
;
10318 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10320 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10323 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10324 ULONG helpStringContext
)
10326 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10327 FIXME("%p %u - stub\n", This
, helpStringContext
);
10331 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10334 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10335 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10338 return E_INVALIDARG
;
10340 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10345 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10346 ICreateTypeLib2_fnQueryInterface
,
10347 ICreateTypeLib2_fnAddRef
,
10348 ICreateTypeLib2_fnRelease
,
10349 ICreateTypeLib2_fnCreateTypeInfo
,
10350 ICreateTypeLib2_fnSetName
,
10351 ICreateTypeLib2_fnSetVersion
,
10352 ICreateTypeLib2_fnSetGuid
,
10353 ICreateTypeLib2_fnSetDocString
,
10354 ICreateTypeLib2_fnSetHelpFileName
,
10355 ICreateTypeLib2_fnSetHelpContext
,
10356 ICreateTypeLib2_fnSetLcid
,
10357 ICreateTypeLib2_fnSetLibFlags
,
10358 ICreateTypeLib2_fnSaveAllChanges
,
10359 ICreateTypeLib2_fnDeleteTypeInfo
,
10360 ICreateTypeLib2_fnSetCustData
,
10361 ICreateTypeLib2_fnSetHelpStringContext
,
10362 ICreateTypeLib2_fnSetHelpStringDll
10365 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10366 REFIID riid
, void **object
)
10368 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10370 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10373 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10375 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10377 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10380 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10382 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10384 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10387 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10390 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10392 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10394 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10399 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10402 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10406 TRACE("%p %x\n", This
, typeFlags
);
10408 if (typeFlags
& TYPEFLAG_FDUAL
) {
10409 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10411 ITypeInfo
*dispatch
;
10415 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10419 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10420 ITypeLib_Release(stdole
);
10424 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10425 ITypeInfo_Release(dispatch
);
10430 old_flags
= This
->typeattr
.wTypeFlags
;
10431 This
->typeattr
.wTypeFlags
= typeFlags
;
10433 hres
= ICreateTypeInfo2_LayOut(iface
);
10434 if (FAILED(hres
)) {
10435 This
->typeattr
.wTypeFlags
= old_flags
;
10442 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10445 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10447 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10450 return E_INVALIDARG
;
10452 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10457 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10460 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10462 TRACE("%p %d\n", This
, helpContext
);
10464 This
->dwHelpContext
= helpContext
;
10469 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10470 WORD majorVerNum
, WORD minorVerNum
)
10472 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10474 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10476 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10477 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10482 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10483 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10485 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10487 ITypeLib
*container
;
10488 TLBRefType
*ref_type
;
10490 TYPEATTR
*typeattr
;
10494 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10496 if (!typeInfo
|| !refType
)
10497 return E_INVALIDARG
;
10499 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10503 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10504 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10506 ITypeLib_Release(container
);
10508 *refType
= target
->hreftype
;
10513 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10514 if (FAILED(hres
)) {
10515 ITypeLib_Release(container
);
10519 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10520 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10521 implib
->lcid
== libattr
->lcid
&&
10522 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10523 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10527 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10528 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10530 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10531 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10532 implib
->name
= SysAllocString(our_container
->path
);
10534 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10535 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10537 implib
->name
= NULL
;
10538 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10542 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10543 implib
->lcid
= libattr
->lcid
;
10544 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10545 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10547 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10550 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10551 ITypeLib_Release(container
);
10553 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10558 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10559 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10560 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10561 ref_type
->tkind
== typeattr
->typekind
)
10566 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10567 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10569 ref_type
->tkind
= typeattr
->typekind
;
10570 ref_type
->pImpTLInfo
= implib
;
10571 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10573 ref_type
->index
= TLB_REF_USE_GUID
;
10575 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10577 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10580 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10582 *refType
= ref_type
->reference
| 0x1;
10584 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10585 This
->pTypeLib
->dispatch_href
= *refType
;
10590 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10591 UINT index
, FUNCDESC
*funcDesc
)
10593 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10594 TLBFuncDesc tmp_func_desc
, *func_desc
;
10599 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10601 if (!funcDesc
|| funcDesc
->oVft
& 3)
10602 return E_INVALIDARG
;
10604 switch (This
->typeattr
.typekind
) {
10606 if (funcDesc
->funckind
!= FUNC_STATIC
)
10607 return TYPE_E_BADMODULEKIND
;
10609 case TKIND_DISPATCH
:
10610 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10611 return TYPE_E_BADMODULEKIND
;
10614 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10615 return TYPE_E_BADMODULEKIND
;
10618 if (index
> This
->typeattr
.cFuncs
)
10619 return TYPE_E_ELEMENTNOTFOUND
;
10621 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10622 !funcDesc
->cParams
)
10623 return TYPE_E_INCONSISTENTPROPFUNCS
;
10626 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10627 funcDesc
->oVft
% 8 != 0)
10628 return E_INVALIDARG
;
10631 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10632 TLBFuncDesc_Constructor(&tmp_func_desc
);
10634 tmp_func_desc
.funcdesc
= *funcDesc
;
10636 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10637 tmp_func_desc
.funcdesc
.oVft
|= 1;
10639 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10640 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10641 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10643 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10644 tmp_func_desc
.funcdesc
.cScodes
= 0;
10647 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10648 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10649 buf_size
+= sizeof(ELEMDESC
);
10650 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10652 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10653 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10655 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10656 if (FAILED(hres
)) {
10657 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10658 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10662 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10663 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10664 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10665 if (FAILED(hres
)) {
10666 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10667 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10670 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10671 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10672 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10673 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10674 if (FAILED(hres
)) {
10675 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10676 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10682 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10684 if (This
->funcdescs
) {
10685 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10686 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10688 if (index
< This
->typeattr
.cFuncs
) {
10689 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10690 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10691 func_desc
= This
->funcdescs
+ index
;
10693 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10695 /* move custdata lists to the new memory location */
10696 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10698 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10699 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10700 list_init(&fd
->custdata_list
);
10702 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10703 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10708 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10710 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10711 list_init(&func_desc
->custdata_list
);
10713 ++This
->typeattr
.cFuncs
;
10715 This
->needs_layout
= TRUE
;
10720 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10721 UINT index
, HREFTYPE refType
)
10723 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10724 TLBImplType
*impl_type
;
10727 TRACE("%p %u %d\n", This
, index
, refType
);
10729 switch(This
->typeattr
.typekind
){
10730 case TKIND_COCLASS
: {
10732 FIXME("Unhandled index: -1\n");
10736 if(index
!= This
->typeattr
.cImplTypes
)
10737 return TYPE_E_ELEMENTNOTFOUND
;
10741 case TKIND_INTERFACE
:
10742 case TKIND_DISPATCH
:
10743 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10744 return TYPE_E_ELEMENTNOTFOUND
;
10747 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10751 if (This
->impltypes
){
10754 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10755 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10757 if (index
< This
->typeattr
.cImplTypes
) {
10758 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10759 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10760 impl_type
= This
->impltypes
+ index
;
10762 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10764 /* move custdata lists to the new memory location */
10765 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10767 TLBImplType
*it
= &This
->impltypes
[i
];
10768 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10769 list_init(&it
->custdata_list
);
10771 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10772 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10777 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10779 memset(impl_type
, 0, sizeof(TLBImplType
));
10780 TLBImplType_Constructor(impl_type
);
10781 impl_type
->hRef
= refType
;
10783 ++This
->typeattr
.cImplTypes
;
10785 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10786 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10788 hres
= ICreateTypeInfo2_LayOut(iface
);
10795 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10796 UINT index
, INT implTypeFlags
)
10798 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10799 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10801 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10803 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10804 return TYPE_E_BADMODULEKIND
;
10806 if (index
>= This
->typeattr
.cImplTypes
)
10807 return TYPE_E_ELEMENTNOTFOUND
;
10809 impl_type
->implflags
= implTypeFlags
;
10814 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10817 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10819 TRACE("%p %d\n", This
, alignment
);
10821 This
->typeattr
.cbAlignment
= alignment
;
10826 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10829 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10831 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10834 return E_INVALIDARG
;
10836 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10838 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10843 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10844 UINT index
, VARDESC
*varDesc
)
10846 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10847 TLBVarDesc
*var_desc
;
10849 TRACE("%p %u %p\n", This
, index
, varDesc
);
10851 if (This
->vardescs
){
10854 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10855 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
10857 if (index
< This
->typeattr
.cVars
) {
10858 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10859 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
10860 var_desc
= This
->vardescs
+ index
;
10862 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
10864 /* move custdata lists to the new memory location */
10865 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
10867 TLBVarDesc
*var
= &This
->vardescs
[i
];
10868 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10869 list_init(&var
->custdata_list
);
10871 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10872 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10877 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10879 TLBVarDesc_Constructor(var_desc
);
10880 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10881 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10883 ++This
->typeattr
.cVars
;
10885 This
->needs_layout
= TRUE
;
10890 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10891 UINT index
, LPOLESTR
*names
, UINT numNames
)
10893 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10894 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10897 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10900 return E_INVALIDARG
;
10902 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
10903 return TYPE_E_ELEMENTNOTFOUND
;
10905 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10906 if(numNames
> func_desc
->funcdesc
.cParams
)
10907 return TYPE_E_ELEMENTNOTFOUND
;
10909 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10910 return TYPE_E_ELEMENTNOTFOUND
;
10912 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
10913 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10914 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10915 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10916 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10917 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10919 return TYPE_E_AMBIGUOUSNAME
;
10923 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10925 for (i
= 1; i
< numNames
; ++i
) {
10926 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10927 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10933 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10934 UINT index
, LPOLESTR name
)
10936 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10938 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10941 return E_INVALIDARG
;
10943 if(index
>= This
->typeattr
.cVars
)
10944 return TYPE_E_ELEMENTNOTFOUND
;
10946 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10950 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10951 TYPEDESC
*tdescAlias
)
10953 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10956 TRACE("%p %p\n", This
, tdescAlias
);
10959 return E_INVALIDARG
;
10961 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
10962 return TYPE_E_BADMODULEKIND
;
10964 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
10968 heap_free(This
->tdescAlias
);
10969 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10970 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10975 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10976 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10978 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10979 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10983 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10984 UINT index
, LPOLESTR docString
)
10986 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10987 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10989 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10992 return E_INVALIDARG
;
10994 if(index
>= This
->typeattr
.cFuncs
)
10995 return TYPE_E_ELEMENTNOTFOUND
;
10997 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11002 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
11003 UINT index
, LPOLESTR docString
)
11005 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11006 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11008 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11011 return E_INVALIDARG
;
11013 if(index
>= This
->typeattr
.cVars
)
11014 return TYPE_E_ELEMENTNOTFOUND
;
11016 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11021 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
11022 UINT index
, DWORD helpContext
)
11024 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11025 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11027 TRACE("%p %u %d\n", This
, index
, helpContext
);
11029 if(index
>= This
->typeattr
.cFuncs
)
11030 return TYPE_E_ELEMENTNOTFOUND
;
11032 func_desc
->helpcontext
= helpContext
;
11037 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
11038 UINT index
, DWORD helpContext
)
11040 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11041 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11043 TRACE("%p %u %d\n", This
, index
, helpContext
);
11045 if(index
>= This
->typeattr
.cVars
)
11046 return TYPE_E_ELEMENTNOTFOUND
;
11048 var_desc
->HelpContext
= helpContext
;
11053 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
11054 UINT index
, BSTR bstrMops
)
11056 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11057 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
11061 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
11064 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11066 TRACE("%p %p\n", This
, idlDesc
);
11069 return E_INVALIDARG
;
11071 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11072 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11077 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11079 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11081 TLBFuncDesc
*func_desc
;
11082 UINT user_vft
= 0, i
, depth
= 0;
11083 HRESULT hres
= S_OK
;
11085 TRACE("%p\n", This
);
11087 This
->needs_layout
= FALSE
;
11089 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
11093 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11098 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11100 if (SUCCEEDED(hres
)) {
11101 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11103 if (SUCCEEDED(hres
)) {
11104 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11105 if (FAILED(hres
)) {
11106 ITypeInfo_Release(inh
);
11107 ITypeInfo_Release(tinfo
);
11110 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11111 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11115 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11116 if(SUCCEEDED(hres
)){
11118 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11119 if(SUCCEEDED(hres
)){
11120 ITypeInfo_Release(inh
);
11124 }while(SUCCEEDED(hres
));
11127 ITypeInfo_Release(inh
);
11128 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11129 This
->typeattr
.cbSizeVft
= 0;
11132 ITypeInfo_Release(tinfo
);
11135 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11136 This
->typeattr
.cbSizeVft
= 0;
11139 ITypeInfo_Release(tinfo
);
11142 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11143 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11145 This
->typeattr
.cbSizeVft
= 0;
11147 func_desc
= This
->funcdescs
;
11149 while (i
< This
->typeattr
.cFuncs
) {
11150 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11151 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11153 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11154 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11156 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11158 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11161 BOOL reset
= FALSE
;
11163 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11165 iter
= This
->funcdescs
;
11166 while (j
< This
->typeattr
.cFuncs
) {
11167 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11169 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11172 ++func_desc
->funcdesc
.memid
;
11173 iter
= This
->funcdescs
;
11186 if (user_vft
> This
->typeattr
.cbSizeVft
)
11187 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11189 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11190 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11191 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11193 BOOL reset
= FALSE
;
11196 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11198 iter
= This
->vardescs
;
11199 while (j
< This
->typeattr
.cVars
) {
11200 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11202 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11205 ++var_desc
->vardesc
.memid
;
11206 iter
= This
->vardescs
;
11216 ITypeInfo_Release(tinfo
);
11220 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11223 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11224 FIXME("%p %u - stub\n", This
, index
);
11228 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11229 MEMBERID memid
, INVOKEKIND invKind
)
11231 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11232 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11236 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11239 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11240 FIXME("%p %u - stub\n", This
, index
);
11244 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11247 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11248 FIXME("%p %x - stub\n", This
, memid
);
11252 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11255 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11256 FIXME("%p %u - stub\n", This
, index
);
11260 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11261 REFGUID guid
, VARIANT
*varVal
)
11265 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11267 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11269 if (!guid
|| !varVal
)
11270 return E_INVALIDARG
;
11272 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11274 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11277 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11278 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11280 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11281 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11285 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11286 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11288 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11289 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11293 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11294 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11296 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11297 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11301 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11302 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11304 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11305 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11309 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11310 ULONG helpStringContext
)
11312 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11314 TRACE("%p %u\n", This
, helpStringContext
);
11316 This
->dwHelpStringContext
= helpStringContext
;
11321 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11322 UINT index
, ULONG helpStringContext
)
11324 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11325 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11329 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11330 UINT index
, ULONG helpStringContext
)
11332 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11333 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11337 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11339 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11340 FIXME("%p - stub\n", This
);
11344 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11347 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11349 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11352 return E_INVALIDARG
;
11354 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11359 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11360 ICreateTypeInfo2_fnQueryInterface
,
11361 ICreateTypeInfo2_fnAddRef
,
11362 ICreateTypeInfo2_fnRelease
,
11363 ICreateTypeInfo2_fnSetGuid
,
11364 ICreateTypeInfo2_fnSetTypeFlags
,
11365 ICreateTypeInfo2_fnSetDocString
,
11366 ICreateTypeInfo2_fnSetHelpContext
,
11367 ICreateTypeInfo2_fnSetVersion
,
11368 ICreateTypeInfo2_fnAddRefTypeInfo
,
11369 ICreateTypeInfo2_fnAddFuncDesc
,
11370 ICreateTypeInfo2_fnAddImplType
,
11371 ICreateTypeInfo2_fnSetImplTypeFlags
,
11372 ICreateTypeInfo2_fnSetAlignment
,
11373 ICreateTypeInfo2_fnSetSchema
,
11374 ICreateTypeInfo2_fnAddVarDesc
,
11375 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11376 ICreateTypeInfo2_fnSetVarName
,
11377 ICreateTypeInfo2_fnSetTypeDescAlias
,
11378 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11379 ICreateTypeInfo2_fnSetFuncDocString
,
11380 ICreateTypeInfo2_fnSetVarDocString
,
11381 ICreateTypeInfo2_fnSetFuncHelpContext
,
11382 ICreateTypeInfo2_fnSetVarHelpContext
,
11383 ICreateTypeInfo2_fnSetMops
,
11384 ICreateTypeInfo2_fnSetTypeIdldesc
,
11385 ICreateTypeInfo2_fnLayOut
,
11386 ICreateTypeInfo2_fnDeleteFuncDesc
,
11387 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11388 ICreateTypeInfo2_fnDeleteVarDesc
,
11389 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11390 ICreateTypeInfo2_fnDeleteImplType
,
11391 ICreateTypeInfo2_fnSetCustData
,
11392 ICreateTypeInfo2_fnSetFuncCustData
,
11393 ICreateTypeInfo2_fnSetParamCustData
,
11394 ICreateTypeInfo2_fnSetVarCustData
,
11395 ICreateTypeInfo2_fnSetImplTypeCustData
,
11396 ICreateTypeInfo2_fnSetHelpStringContext
,
11397 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11398 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11399 ICreateTypeInfo2_fnInvalidate
,
11400 ICreateTypeInfo2_fnSetName
11403 /******************************************************************************
11404 * ClearCustData (OLEAUT32.171)
11406 * Clear a custom data type's data.
11409 * lpCust [I] The custom data type instance
11414 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11416 if (lpCust
&& lpCust
->cCustData
)
11418 if (lpCust
->prgCustData
)
11422 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11423 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11425 CoTaskMemFree(lpCust
->prgCustData
);
11426 lpCust
->prgCustData
= NULL
;
11428 lpCust
->cCustData
= 0;