4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
46 * -. lousy fatal error handling
57 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
58 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
72 WORD type_id
; /* Type identifier */
73 WORD count
; /* Number of resources of this type */
74 DWORD resloader
; /* SetResourceHandler() */
80 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
81 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
82 static void TLB_FreeVarDesc(VARDESC
*);
84 /****************************************************************************
87 * Takes p_iVal (which is in little endian) and returns it
88 * in the host machine's byte order.
90 #ifdef WORDS_BIGENDIAN
91 static WORD
FromLEWord(WORD p_iVal
)
93 return (((p_iVal
& 0x00FF) << 8) |
94 ((p_iVal
& 0xFF00) >> 8));
98 static DWORD
FromLEDWord(DWORD p_iVal
)
100 return (((p_iVal
& 0x000000FF) << 24) |
101 ((p_iVal
& 0x0000FF00) << 8) |
102 ((p_iVal
& 0x00FF0000) >> 8) |
103 ((p_iVal
& 0xFF000000) >> 24));
106 #define FromLEWord(X) (X)
107 #define FromLEDWord(X) (X)
110 #define DISPATCH_HREF_OFFSET 0x01000000
111 #define DISPATCH_HREF_MASK 0xff000000
113 /****************************************************************************
116 * Fix byte order in any structure if necessary
118 #ifdef WORDS_BIGENDIAN
119 static void FromLEWords(void *p_Val
, int p_iSize
)
123 p_iSize
/= sizeof(WORD
);
126 *Val
= FromLEWord(*Val
);
133 static void FromLEDWords(void *p_Val
, int p_iSize
)
137 p_iSize
/= sizeof(DWORD
);
140 *Val
= FromLEDWord(*Val
);
146 #define FromLEWords(X,Y) /*nothing*/
147 #define FromLEDWords(X,Y) /*nothing*/
151 * Find a typelib key which matches a requested maj.min version.
153 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
155 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
159 INT best_maj
= -1, best_min
= -1;
162 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
163 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
165 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
168 len
= sizeof(key_name
);
170 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
174 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
176 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
178 if (*wMaj
== 0xffff && *wMin
== 0xffff)
180 if (v_maj
> best_maj
) best_maj
= v_maj
;
181 if (v_min
> best_min
) best_min
= v_min
;
183 else if (*wMaj
== v_maj
)
190 break; /* exact match */
192 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
195 len
= sizeof(key_name
);
199 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
201 if (*wMaj
== 0xffff && *wMin
== 0xffff)
203 if (best_maj
>= 0 && best_min
>= 0)
211 if (*wMaj
== best_maj
&& best_min
>= 0)
219 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
220 /* buffer must be at least 60 characters long */
221 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
223 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
224 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
226 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
227 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
228 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
232 /* get the path of an interface key, in the form "Interface\\<guid>" */
233 /* buffer must be at least 50 characters long */
234 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
236 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
238 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
239 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
243 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
244 /* buffer must be at least 16 characters long */
245 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
247 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
248 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
249 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
250 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
252 sprintfW( buffer
, LcidFormatW
, lcid
);
255 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
256 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
257 case SYS_WIN64
: strcatW( buffer
, win64W
); break;
259 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
265 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
267 struct tlibredirect_data
281 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
282 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
283 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
285 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
289 WCHAR Path
[MAX_PATH
];
292 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
296 ACTCTX_SECTION_KEYED_DATA data
;
298 data
.cbSize
= sizeof(data
);
299 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
301 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
305 if ((wMaj
!= 0xffff || wMin
!= 0xffff) && (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
))
306 return TYPE_E_LIBNOTREGISTERED
;
308 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
309 len
= SearchPathW( NULL
, nameW
, NULL
, sizeof(Path
)/sizeof(WCHAR
), Path
, NULL
);
310 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
312 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
313 *path
= SysAllocString( Path
);
318 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
319 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
321 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
322 if (res
== ERROR_FILE_NOT_FOUND
)
324 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
325 return TYPE_E_LIBNOTREGISTERED
;
327 else if (res
!= ERROR_SUCCESS
)
329 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
330 return TYPE_E_REGISTRYACCESS
;
335 LONG dwPathLen
= sizeof(Path
);
337 get_lcid_subkey( myLCID
, syskind
, buffer
);
339 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
343 else if (myLCID
== lcid
)
345 /* try with sub-langid */
346 myLCID
= SUBLANGID(lcid
);
348 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
350 /* try with system langid */
360 *path
= SysAllocString( Path
);
365 TRACE_(typelib
)("-- 0x%08x\n", hr
);
369 /****************************************************************************
370 * QueryPathOfRegTypeLib [OLEAUT32.164]
372 * Gets the path to a registered type library.
375 * guid [I] referenced guid
376 * wMaj [I] major version
377 * wMin [I] minor version
379 * path [O] path of typelib
383 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
384 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
387 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
391 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
396 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
399 /******************************************************************************
400 * CreateTypeLib [OLEAUT32.160] creates a typelib
406 HRESULT WINAPI
CreateTypeLib(
407 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
409 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
413 /******************************************************************************
414 * LoadTypeLib [OLEAUT32.161]
416 * Loads a type library
419 * szFile [I] Name of file to load from.
420 * pptLib [O] Pointer that receives ITypeLib object on success.
427 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
429 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
431 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
432 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
435 /******************************************************************************
436 * LoadTypeLibEx [OLEAUT32.183]
438 * Loads and optionally registers a type library
444 HRESULT WINAPI
LoadTypeLibEx(
445 LPCOLESTR szFile
, /* [in] Name of file to load from */
446 REGKIND regkind
, /* [in] Specify kind of registration */
447 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
449 WCHAR szPath
[MAX_PATH
+1];
452 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
454 if (!szFile
|| !pptLib
)
459 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
464 case REGKIND_DEFAULT
:
465 /* don't register typelibs supplied with full path. Experimentation confirms the following */
466 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
467 (szFile
[0] && (szFile
[1] == ':'))) break;
468 /* else fall-through */
470 case REGKIND_REGISTER
:
471 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
473 ITypeLib_Release(*pptLib
);
481 TRACE(" returns %08x\n",res
);
485 /******************************************************************************
486 * LoadRegTypeLib [OLEAUT32.162]
488 * Loads a registered type library.
491 * rguid [I] GUID of the registered type library.
492 * wVerMajor [I] major version.
493 * wVerMinor [I] minor version.
494 * lcid [I] locale ID.
495 * ppTLib [O] pointer that receives an ITypeLib object on success.
499 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
502 HRESULT WINAPI
LoadRegTypeLib(
514 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
518 res
= LoadTypeLib(bstr
, ppTLib
);
521 if ((wVerMajor
!=0xffff || wVerMinor
!=0xffff) && *ppTLib
)
525 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
528 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
529 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
533 ITypeLib_Release(*ppTLib
);
535 res
= TYPE_E_LIBNOTREGISTERED
;
541 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
547 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
548 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
549 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
550 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
551 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
552 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
554 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
559 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
560 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
561 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
563 get_interface_key( &tattr
->guid
, keyName
);
564 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
565 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
568 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
569 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
571 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
572 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
573 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
574 (const BYTE
*)PSOA
, sizeof PSOA
);
578 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
579 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
580 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
581 (const BYTE
*)PSOA
, sizeof PSOA
);
585 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
586 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
589 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
590 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
592 StringFromGUID2(&libattr
->guid
, buffer
, 40);
593 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
594 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
595 sprintfW(buffer
, fmtver
, libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
596 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
597 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
605 /******************************************************************************
606 * RegisterTypeLib [OLEAUT32.163]
607 * Adds information about a type library to the System Registry
609 * Docs: ITypeLib FAR * ptlib
610 * Docs: OLECHAR FAR* szFullPath
611 * Docs: OLECHAR FAR* szHelpDir
617 HRESULT WINAPI
RegisterTypeLib(
618 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
619 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
620 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
632 if (ptlib
== NULL
|| szFullPath
== NULL
)
635 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
639 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
642 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
645 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
646 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
650 /* Set the human-readable name of the typelib */
651 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
655 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
656 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
662 /* Make up the name of the typelib path subkey */
663 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
665 /* Create the typelib path subkey */
666 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
667 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
669 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
670 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
678 /* Create the flags subkey */
679 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
680 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
682 /* FIXME: is %u correct? */
683 static const WCHAR formatW
[] = {'%','u',0};
685 sprintfW(buf
, formatW
, attr
->wLibFlags
);
686 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
687 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
695 /* create the helpdir subkey */
696 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
697 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
699 BOOL freeHelpDir
= FALSE
;
702 /* if we created a new key, and helpDir was null, set the helpdir
703 to the directory which contains the typelib. However,
704 if we just opened an existing key, we leave the helpdir alone */
705 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
706 szHelpDir
= SysAllocString(szFullPath
);
707 pIndexStr
= strrchrW(szHelpDir
, '\\');
714 /* if we have an szHelpDir, set it! */
715 if (szHelpDir
!= NULL
) {
716 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
717 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
723 if (freeHelpDir
) SysFreeString(szHelpDir
);
735 /* register OLE Automation-compatible interfaces for this typelib */
736 types
= ITypeLib_GetTypeInfoCount(ptlib
);
737 for (tidx
=0; tidx
<types
; tidx
++) {
738 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
739 LPOLESTR name
= NULL
;
740 ITypeInfo
*tinfo
= NULL
;
742 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
745 case TKIND_INTERFACE
:
746 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
747 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
751 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
752 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
756 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
761 TYPEATTR
*tattr
= NULL
;
762 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
765 TRACE_(typelib
)("guid=%s, flags=%04x (",
766 debugstr_guid(&tattr
->guid
),
769 if (TRACE_ON(typelib
)) {
770 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
790 /* Register all dispinterfaces (which includes dual interfaces) and
791 oleautomation interfaces */
792 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
793 kind
== TKIND_DISPATCH
)
796 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
798 /* register interface<->typelib coupling */
799 TLB_register_interface(attr
, name
, tattr
, 0);
801 /* register TLBs into the opposite registry view, too */
802 if(opposite
== KEY_WOW64_32KEY
||
803 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
804 TLB_register_interface(attr
, name
, tattr
, opposite
);
807 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
810 ITypeInfo_Release(tinfo
);
817 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
822 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
824 WCHAR subKeyName
[50];
827 /* the path to the type */
828 get_interface_key( guid
, subKeyName
);
830 /* Delete its bits */
831 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
834 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
835 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
836 RegDeleteKeyW(subKey
, TypeLibW
);
838 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
841 /******************************************************************************
842 * UnRegisterTypeLib [OLEAUT32.186]
843 * Removes information about a type library from the System Registry
850 HRESULT WINAPI
UnRegisterTypeLib(
851 REFGUID libid
, /* [in] Guid of the library */
852 WORD wVerMajor
, /* [in] major version */
853 WORD wVerMinor
, /* [in] minor version */
854 LCID lcid
, /* [in] locale id */
857 BSTR tlibPath
= NULL
;
860 WCHAR subKeyName
[50];
863 BOOL deleteOtherStuff
;
865 TYPEATTR
* typeAttr
= NULL
;
867 ITypeInfo
* typeInfo
= NULL
;
868 ITypeLib
* typeLib
= NULL
;
871 TRACE("(IID: %s)\n",debugstr_guid(libid
));
873 /* Create the path to the key */
874 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
876 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
878 TRACE("Unsupported syskind %i\n", syskind
);
879 result
= E_INVALIDARG
;
883 /* get the path to the typelib on disk */
884 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
885 result
= E_INVALIDARG
;
889 /* Try and open the key to the type library. */
890 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
891 result
= E_INVALIDARG
;
895 /* Try and load the type library */
896 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
897 result
= TYPE_E_INVALIDSTATE
;
901 /* remove any types registered with this typelib */
902 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
903 for (i
=0; i
<numTypes
; i
++) {
904 /* get the kind of type */
905 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
909 /* skip non-interfaces, and get type info for the type */
910 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
913 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
916 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
920 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
921 kind
== TKIND_DISPATCH
)
924 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
926 TLB_unregister_interface(&typeAttr
->guid
, 0);
928 /* unregister TLBs into the opposite registry view, too */
929 if(opposite
== KEY_WOW64_32KEY
||
930 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
931 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
936 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
938 if (typeInfo
) ITypeInfo_Release(typeInfo
);
942 /* Now, delete the type library path subkey */
943 get_lcid_subkey( lcid
, syskind
, subKeyName
);
944 RegDeleteKeyW(key
, subKeyName
);
945 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
946 RegDeleteKeyW(key
, subKeyName
);
948 /* check if there is anything besides the FLAGS/HELPDIR keys.
949 If there is, we don't delete them */
950 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
951 deleteOtherStuff
= TRUE
;
953 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
954 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
956 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
957 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
958 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
959 deleteOtherStuff
= FALSE
;
963 /* only delete the other parts of the key if we're absolutely sure */
964 if (deleteOtherStuff
) {
965 RegDeleteKeyW(key
, FLAGSW
);
966 RegDeleteKeyW(key
, HELPDIRW
);
970 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
971 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
972 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
976 SysFreeString(tlibPath
);
977 if (typeLib
) ITypeLib_Release(typeLib
);
978 if (key
) RegCloseKey(key
);
982 /******************************************************************************
983 * RegisterTypeLibForUser [OLEAUT32.442]
984 * Adds information about a type library to the user registry
986 * Docs: ITypeLib FAR * ptlib
987 * Docs: OLECHAR FAR* szFullPath
988 * Docs: OLECHAR FAR* szHelpDir
994 HRESULT WINAPI
RegisterTypeLibForUser(
995 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
996 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
997 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1000 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1001 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1002 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1005 /******************************************************************************
1006 * UnRegisterTypeLibForUser [OLEAUT32.443]
1007 * Removes information about a type library from the user registry
1013 HRESULT WINAPI
UnRegisterTypeLibForUser(
1014 REFGUID libid
, /* [in] GUID of the library */
1015 WORD wVerMajor
, /* [in] major version */
1016 WORD wVerMinor
, /* [in] minor version */
1017 LCID lcid
, /* [in] locale id */
1020 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1021 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1022 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1025 /*======================= ITypeLib implementation =======================*/
1027 typedef struct tagTLBGuid
{
1034 typedef struct tagTLBCustData
1041 /* data structure for import typelibs */
1042 typedef struct tagTLBImpLib
1044 int offset
; /* offset in the file (MSFT)
1045 offset in nametable (SLTG)
1046 just used to identify library while reading
1048 TLBGuid
*guid
; /* libid */
1049 BSTR name
; /* name */
1051 LCID lcid
; /* lcid of imported typelib */
1053 WORD wVersionMajor
; /* major version number */
1054 WORD wVersionMinor
; /* minor version number */
1056 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1057 NULL if not yet loaded */
1061 typedef struct tagTLBString
{
1067 /* internal ITypeLib data */
1068 typedef struct tagITypeLibImpl
1070 ITypeLib2 ITypeLib2_iface
;
1071 ITypeComp ITypeComp_iface
;
1072 ICreateTypeLib2 ICreateTypeLib2_iface
;
1083 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1084 * exported to the application as a UNICODE string.
1086 struct list string_list
;
1087 struct list name_list
;
1088 struct list guid_list
;
1090 const TLBString
*Name
;
1091 const TLBString
*DocString
;
1092 const TLBString
*HelpFile
;
1093 const TLBString
*HelpStringDll
;
1094 DWORD dwHelpContext
;
1095 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1096 struct tagITypeInfoImpl
**typeinfos
;
1097 struct list custdata_list
;
1098 struct list implib_list
;
1099 int ctTypeDesc
; /* number of items in type desc array */
1100 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1101 library. Only used while reading MSFT
1103 struct list ref_list
; /* list of ref types in this typelib */
1104 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1107 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1113 static const ITypeLib2Vtbl tlbvt
;
1114 static const ITypeCompVtbl tlbtcvt
;
1115 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1117 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1119 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1122 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1124 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1127 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1129 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1132 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1134 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1137 /* ITypeLib methods */
1138 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1139 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1141 /*======================= ITypeInfo implementation =======================*/
1143 /* data for referenced types */
1144 typedef struct tagTLBRefType
1146 INT index
; /* Type index for internal ref or for external ref
1147 it the format is SLTG. -2 indicates to
1151 TLBGuid
*guid
; /* guid of the referenced type */
1152 /* if index == TLB_REF_USE_GUID */
1154 HREFTYPE reference
; /* The href of this ref */
1155 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1156 TLB_REF_INTERNAL for internal refs
1157 TLB_REF_NOT_FOUND for broken refs */
1162 #define TLB_REF_USE_GUID -2
1164 #define TLB_REF_INTERNAL (void*)-2
1165 #define TLB_REF_NOT_FOUND (void*)-1
1167 /* internal Parameter data */
1168 typedef struct tagTLBParDesc
1170 const TLBString
*Name
;
1171 struct list custdata_list
;
1174 /* internal Function data */
1175 typedef struct tagTLBFuncDesc
1177 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1178 const TLBString
*Name
; /* the name of this function */
1179 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1181 int HelpStringContext
;
1182 const TLBString
*HelpString
;
1183 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1184 struct list custdata_list
;
1187 /* internal Variable data */
1188 typedef struct tagTLBVarDesc
1190 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1191 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1192 const TLBString
*Name
; /* the name of this variable */
1194 int HelpStringContext
;
1195 const TLBString
*HelpString
;
1196 struct list custdata_list
;
1199 /* internal implemented interface data */
1200 typedef struct tagTLBImplType
1202 HREFTYPE hRef
; /* hRef of interface */
1203 int implflags
; /* IMPLFLAG_*s */
1204 struct list custdata_list
;
1207 /* internal TypeInfo data */
1208 typedef struct tagITypeInfoImpl
1210 ITypeInfo2 ITypeInfo2_iface
;
1211 ITypeComp ITypeComp_iface
;
1212 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1214 BOOL not_attached_to_typelib
;
1219 TYPEDESC
*tdescAlias
;
1221 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1222 int index
; /* index in this typelib; */
1223 HREFTYPE hreftype
; /* hreftype for app object binding */
1224 /* type libs seem to store the doc strings in ascii
1225 * so why should we do it in unicode?
1227 const TLBString
*Name
;
1228 const TLBString
*DocString
;
1229 const TLBString
*DllName
;
1230 const TLBString
*Schema
;
1231 DWORD dwHelpContext
;
1232 DWORD dwHelpStringContext
;
1235 TLBFuncDesc
*funcdescs
;
1238 TLBVarDesc
*vardescs
;
1240 /* Implemented Interfaces */
1241 TLBImplType
*impltypes
;
1243 struct list
*pcustdata_list
;
1244 struct list custdata_list
;
1247 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1249 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1252 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1254 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1257 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1259 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1262 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1264 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1267 static const ITypeInfo2Vtbl tinfvt
;
1268 static const ITypeCompVtbl tcompvt
;
1269 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1271 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1272 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1274 typedef struct tagTLBContext
1276 unsigned int oStart
; /* start of TLB in file */
1277 unsigned int pos
; /* current pos */
1278 unsigned int length
; /* total length */
1279 void *mapping
; /* memory mapping */
1280 MSFT_SegDir
* pTblDir
;
1281 ITypeLibImpl
* pLibInfo
;
1285 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1287 return str
!= NULL
? str
->str
: NULL
;
1290 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1294 return memcmp(left
, str
->str
, len
);
1297 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1299 return guid
!= NULL
? &guid
->guid
: NULL
;
1302 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1304 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1307 static int get_ptr_size(SYSKIND syskind
)
1317 WARN("Unhandled syskind: 0x%x\n", syskind
);
1324 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1325 if (pTD
->vt
& VT_RESERVED
)
1326 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1327 if (pTD
->vt
& VT_BYREF
)
1328 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1329 if (pTD
->vt
& VT_ARRAY
)
1330 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1331 if (pTD
->vt
& VT_VECTOR
)
1332 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1333 switch(pTD
->vt
& VT_TYPEMASK
) {
1334 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1335 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1336 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1337 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1338 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1339 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1340 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1341 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1342 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1343 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1344 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1345 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1346 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1347 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1348 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1349 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1350 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1351 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1352 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1353 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1354 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1355 pTD
->u
.hreftype
); break;
1356 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1357 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1358 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1359 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1361 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1362 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1364 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1365 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1366 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1369 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1373 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1375 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1376 dump_TypeDesc(&edesc
->tdesc
,buf
);
1377 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1378 MESSAGE("\t\tu.paramdesc.wParamFlags");
1379 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1380 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1381 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1382 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1383 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1384 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1385 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1386 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1387 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1389 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1391 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1392 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1393 MESSAGE("Param %d:\n",i
);
1394 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1396 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1397 switch (funcdesc
->funckind
) {
1398 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1399 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1400 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1401 case FUNC_STATIC
: MESSAGE("static");break;
1402 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1403 default: MESSAGE("unknown");break;
1405 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1406 switch (funcdesc
->invkind
) {
1407 case INVOKE_FUNC
: MESSAGE("func");break;
1408 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1409 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1410 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1412 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1413 switch (funcdesc
->callconv
) {
1414 case CC_CDECL
: MESSAGE("cdecl");break;
1415 case CC_PASCAL
: MESSAGE("pascal");break;
1416 case CC_STDCALL
: MESSAGE("stdcall");break;
1417 case CC_SYSCALL
: MESSAGE("syscall");break;
1420 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1421 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1422 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1424 MESSAGE("\telemdescFunc (return value type):\n");
1425 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1428 static const char * const typekind_desc
[] =
1441 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1444 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1445 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1446 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1449 dump_FUNCDESC(&(pfd
->funcdesc
));
1451 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1452 if(pfd
->Entry
== NULL
)
1453 MESSAGE("\tentry: (null)\n");
1454 else if(pfd
->Entry
== (void*)-1)
1455 MESSAGE("\tentry: invalid\n");
1456 else if(IS_INTRESOURCE(pfd
->Entry
))
1457 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1459 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1461 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1465 dump_TLBFuncDescOne(pfd
);
1470 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1474 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1480 static void dump_TLBImpLib(const TLBImpLib
*import
)
1482 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1483 debugstr_w(import
->name
));
1484 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1485 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1488 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1492 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1494 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1495 if(ref
->index
== -1)
1496 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1498 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1500 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1502 TRACE_(typelib
)("in lib\n");
1503 dump_TLBImpLib(ref
->pImpTLInfo
);
1508 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1513 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1514 impl
->hRef
, impl
->implflags
);
1520 static void dump_DispParms(const DISPPARAMS
* pdp
)
1524 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1526 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1528 TRACE("named args:\n");
1529 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1530 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1533 if (pdp
->cArgs
&& pdp
->rgvarg
)
1536 for (index
= 0; index
< pdp
->cArgs
; index
++)
1537 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1541 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1543 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1544 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1545 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1546 TRACE("kind:%s\n", typekind_desc
[pty
->typeattr
.typekind
]);
1547 TRACE("fct:%u var:%u impl:%u\n", pty
->typeattr
.cFuncs
, pty
->typeattr
.cVars
, pty
->typeattr
.cImplTypes
);
1548 TRACE("wTypeFlags: 0x%04x\n", pty
->typeattr
.wTypeFlags
);
1549 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1550 if (pty
->typeattr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1552 dump_TLBFuncDesc(pty
->funcdescs
, pty
->typeattr
.cFuncs
);
1553 dump_TLBVarDesc(pty
->vardescs
, pty
->typeattr
.cVars
);
1554 dump_TLBImplType(pty
->impltypes
, pty
->typeattr
.cImplTypes
);
1557 static void dump_VARDESC(const VARDESC
*v
)
1559 MESSAGE("memid %d\n",v
->memid
);
1560 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1561 MESSAGE("oInst %d\n",v
->u
.oInst
);
1562 dump_ELEMDESC(&(v
->elemdescVar
));
1563 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1564 MESSAGE("varkind %d\n",v
->varkind
);
1567 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1569 /* VT_LPWSTR is largest type that, may appear in type description */
1570 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1571 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1572 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1573 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1574 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1575 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1576 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1577 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1580 static void TLB_abort(void)
1585 /* returns the size required for a deep copy of a typedesc into a
1587 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1591 if (alloc_initial_space
)
1592 size
+= sizeof(TYPEDESC
);
1598 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1601 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1602 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1608 /* deep copy a typedesc into a flat buffer */
1609 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1614 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1623 dest
->u
.lptdesc
= buffer
;
1624 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1627 dest
->u
.lpadesc
= buffer
;
1628 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1629 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1630 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1636 /* free custom data allocated by MSFT_CustData */
1637 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1639 TLBCustData
*cd
, *cdn
;
1640 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1642 list_remove(&cd
->entry
);
1643 VariantClear(&cd
->data
);
1648 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1653 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1654 ret
= SysAllocStringLen(NULL
, len
- 1);
1655 if (!ret
) return ret
;
1656 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1660 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1661 UINT n
, MEMBERID memid
)
1664 if(funcdescs
->funcdesc
.memid
== memid
)
1672 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1673 UINT n
, MEMBERID memid
)
1676 if(vardescs
->vardesc
.memid
== memid
)
1684 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1685 UINT n
, const OLECHAR
*name
)
1688 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1696 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1698 TLBCustData
*cust_data
;
1699 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1700 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1705 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1706 UINT n
, const OLECHAR
*name
)
1709 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1717 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1719 list_init(&var_desc
->custdata_list
);
1722 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1726 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1731 TLBVarDesc_Constructor(&ret
[n
-1]);
1738 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1742 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1747 list_init(&ret
[n
-1].custdata_list
);
1754 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1756 list_init(&func_desc
->custdata_list
);
1759 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1763 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1768 TLBFuncDesc_Constructor(&ret
[n
-1]);
1775 static void TLBImplType_Constructor(TLBImplType
*impl
)
1777 list_init(&impl
->custdata_list
);
1780 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1784 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1789 TLBImplType_Constructor(&ret
[n
-1]);
1796 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1797 const GUID
*new_guid
, HREFTYPE hreftype
)
1801 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1802 if (IsEqualGUID(&guid
->guid
, new_guid
))
1806 guid
= heap_alloc(sizeof(TLBGuid
));
1810 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1811 guid
->hreftype
= hreftype
;
1813 list_add_tail(guid_list
, &guid
->entry
);
1818 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1820 TLBCustData
*cust_data
;
1832 return DISP_E_BADVARTYPE
;
1835 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1838 cust_data
= heap_alloc(sizeof(TLBCustData
));
1840 return E_OUTOFMEMORY
;
1842 cust_data
->guid
= tlbguid
;
1843 VariantInit(&cust_data
->data
);
1845 list_add_tail(custdata_list
, &cust_data
->entry
);
1847 VariantClear(&cust_data
->data
);
1849 return VariantCopy(&cust_data
->data
, var
);
1852 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1859 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1860 if (strcmpW(str
->str
, new_str
) == 0)
1864 str
= heap_alloc(sizeof(TLBString
));
1868 str
->str
= SysAllocString(new_str
);
1874 list_add_tail(string_list
, &str
->entry
);
1879 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1880 ULONG
*size
, WORD
*align
)
1886 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1890 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1892 ITypeInfo_Release(other
);
1897 *size
= attr
->cbSizeInstance
;
1899 *align
= attr
->cbAlignment
;
1901 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1902 ITypeInfo_Release(other
);
1907 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1908 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1910 ULONG i
, sub
, ptr_size
;
1913 ptr_size
= get_ptr_size(sys
);
1952 *size
= sizeof(DATE
);
1955 *size
= sizeof(VARIANT
);
1957 if(sys
== SYS_WIN32
)
1958 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1962 *size
= sizeof(DECIMAL
);
1969 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
1970 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
1971 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
1976 case VT_USERDEFINED
:
1977 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
1979 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
1993 /**********************************************************************
1995 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1998 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2000 if (where
!= DO_NOT_SEEK
)
2002 where
+= pcx
->oStart
;
2003 if (where
> pcx
->length
)
2006 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2014 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2016 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2017 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2019 MSFT_Seek(pcx
, where
);
2020 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2021 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2026 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2031 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2032 FromLEDWords(buffer
, ret
);
2037 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2042 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2043 FromLEWords(buffer
, ret
);
2048 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2051 MSFT_GuidEntry entry
;
2054 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2056 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2059 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2061 guid
= heap_alloc(sizeof(TLBGuid
));
2063 guid
->offset
= offs
;
2064 guid
->guid
= entry
.guid
;
2065 guid
->hreftype
= entry
.hreftype
;
2067 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2069 offs
+= sizeof(MSFT_GuidEntry
);
2073 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2077 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2078 if(ret
->offset
== offset
){
2079 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2087 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2089 MSFT_NameIntro niName
;
2093 ERR_(typelib
)("bad offset %d\n", offset
);
2097 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2098 pcx
->pTblDir
->pNametab
.offset
+offset
);
2100 return niName
.hreftype
;
2103 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2106 MSFT_NameIntro intro
;
2108 int offs
= 0, lengthInChars
;
2110 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2114 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2117 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2118 intro
.namelen
&= 0xFF;
2119 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2121 len_piece
= (len_piece
+ 4) & ~0x3;
2125 string
= heap_alloc(len_piece
+ 1);
2126 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2127 string
[intro
.namelen
] = '\0';
2129 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2130 string
, -1, NULL
, 0);
2131 if (!lengthInChars
) {
2133 return E_UNEXPECTED
;
2136 tlbstr
= heap_alloc(sizeof(TLBString
));
2138 tlbstr
->offset
= offs
;
2139 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2140 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2144 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2150 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2154 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2155 if (tlbstr
->offset
== offset
) {
2156 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2164 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2168 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2169 if (tlbstr
->offset
== offset
) {
2170 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2179 * read a value and fill a VARIANT structure
2181 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2185 TRACE_(typelib
)("\n");
2187 if(offset
<0) { /* data are packed in here */
2188 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2189 V_I4(pVar
) = offset
& 0x3ffffff;
2192 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2193 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2194 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2195 switch (V_VT(pVar
)){
2196 case VT_EMPTY
: /* FIXME: is this right? */
2197 case VT_NULL
: /* FIXME: is this right? */
2198 case VT_I2
: /* this should not happen */
2209 case VT_VOID
: /* FIXME: is this right? */
2217 case VT_DECIMAL
: /* FIXME: is this right? */
2220 /* pointer types with known behaviour */
2223 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2225 V_BSTR(pVar
) = NULL
;
2227 ptr
= heap_alloc_zero(size
);
2228 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2229 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2230 /* FIXME: do we need a AtoW conversion here? */
2231 V_UNION(pVar
, bstrVal
[size
])='\0';
2232 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2237 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2244 case VT_USERDEFINED
:
2250 case VT_STREAMED_OBJECT
:
2251 case VT_STORED_OBJECT
:
2252 case VT_BLOB_OBJECT
:
2257 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2261 if(size
>0) /* (big|small) endian correct? */
2262 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2266 * create a linked list with custom data
2268 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2274 TRACE_(typelib
)("\n");
2276 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2280 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2281 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2282 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2283 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2284 list_add_head(custdata_list
, &pNew
->entry
);
2285 offset
= entry
.next
;
2290 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2293 pTd
->vt
=type
& VT_TYPEMASK
;
2295 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2297 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2300 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2302 return (invkind
== INVOKE_PROPERTYGET
||
2303 invkind
== INVOKE_PROPERTYPUT
||
2304 invkind
== INVOKE_PROPERTYPUTREF
);
2308 MSFT_DoFuncs(TLBContext
* pcx
,
2313 TLBFuncDesc
** pptfd
)
2316 * member information is stored in a data structure at offset
2317 * indicated by the memoffset field of the typeinfo structure
2318 * There are several distinctive parts.
2319 * The first part starts with a field that holds the total length
2320 * of this (first) part excluding this field. Then follow the records,
2321 * for each member there is one record.
2323 * The first entry is always the length of the record (including this
2325 * The rest of the record depends on the type of the member. If there is
2326 * a field indicating the member type (function, variable, interface, etc)
2327 * I have not found it yet. At this time we depend on the information
2328 * in the type info and the usual order how things are stored.
2330 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2333 * Third is an equal sized array with file offsets to the name entry
2336 * The fourth and last (?) part is an array with offsets to the records
2337 * in the first part of this file segment.
2340 int infolen
, nameoffset
, reclength
, i
;
2341 int recoffset
= offset
+ sizeof(INT
);
2343 char *recbuf
= heap_alloc(0xffff);
2344 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2345 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2347 TRACE_(typelib
)("\n");
2349 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2351 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2353 for ( i
= 0; i
< cFuncs
; i
++ )
2357 /* name, eventually add to a hash table */
2358 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2359 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2361 /* read the function information record */
2362 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2364 reclength
&= 0xffff;
2366 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2368 /* size without argument data */
2369 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2370 if (pFuncRec
->FKCCIC
& 0x1000)
2371 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2373 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2374 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2376 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2377 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2379 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2381 if (pFuncRec
->FKCCIC
& 0x2000 )
2383 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2384 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2385 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2388 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2391 ptfd
->Entry
= (TLBString
*)-1;
2393 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2394 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2396 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2397 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2399 /* fill the FuncDesc Structure */
2400 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2401 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2403 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2404 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2405 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2406 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2407 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2408 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2409 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2411 /* nameoffset is sometimes -1 on the second half of a propget/propput
2412 * pair of functions */
2413 if ((nameoffset
== -1) && (i
> 0) &&
2414 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2415 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2416 ptfd
->Name
= ptfd_prev
->Name
;
2418 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2422 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2424 /* do the parameters/arguments */
2425 if(pFuncRec
->nrargs
)
2428 MSFT_ParameterInfo paraminfo
;
2430 ptfd
->funcdesc
.lprgelemdescParam
=
2431 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2433 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2435 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2436 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2438 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2440 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2446 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2449 if (paraminfo
.oName
!= -1)
2450 ptfd
->pParamDesc
[j
].Name
=
2451 MSFT_ReadName( pcx
, paraminfo
.oName
);
2452 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2455 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2456 (pFuncRec
->FKCCIC
& 0x1000) )
2458 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2460 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2462 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2464 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2465 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2467 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2471 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2474 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2475 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2476 pFuncRec
->FKCCIC
& 0x80 )
2479 pFuncRec
->oArgCustData
[j
],
2480 &ptfd
->pParamDesc
[j
].custdata_list
);
2483 /* SEEK value = jump to offset,
2484 * from there jump to the end of record,
2485 * go back by (j-1) arguments
2487 MSFT_ReadLEDWords( ¶minfo
,
2488 sizeof(MSFT_ParameterInfo
), pcx
,
2489 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2490 * sizeof(MSFT_ParameterInfo
)));
2494 /* scode is not used: archaic win16 stuff FIXME: right? */
2495 ptfd
->funcdesc
.cScodes
= 0 ;
2496 ptfd
->funcdesc
.lprgscode
= NULL
;
2500 recoffset
+= reclength
;
2505 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2506 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2508 int infolen
, nameoffset
, reclength
;
2510 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2515 TRACE_(typelib
)("\n");
2517 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2518 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2519 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2520 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2521 recoffset
+= offset
+sizeof(INT
);
2522 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2523 /* name, eventually add to a hash table */
2524 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2525 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2526 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2527 /* read the variable information record */
2528 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2530 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2533 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2534 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2536 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2537 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2539 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2540 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2542 /* fill the VarDesc Structure */
2543 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2544 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2545 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2546 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2547 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2548 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2549 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2550 if(pVarRec
->VarKind
== VAR_CONST
){
2551 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2552 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2553 pVarRec
->OffsValue
, pcx
);
2555 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2556 recoffset
+= reclength
;
2560 /* process Implemented Interfaces of a com class */
2561 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2565 MSFT_RefRecord refrec
;
2568 TRACE_(typelib
)("\n");
2570 pTI
->impltypes
= TLBImplType_Alloc(count
);
2571 pImpl
= pTI
->impltypes
;
2572 for(i
=0;i
<count
;i
++){
2573 if(offset
<0) break; /* paranoia */
2574 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2575 pImpl
->hRef
= refrec
.reftype
;
2576 pImpl
->implflags
=refrec
.flags
;
2577 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2578 offset
=refrec
.onext
;
2584 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2585 * and some structures, and fix the alignment */
2586 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2588 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2589 switch(info
->tdescAlias
->vt
){
2597 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2598 info
->typeattr
.cbAlignment
= sizeof(void*);
2601 case VT_USERDEFINED
:
2602 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2605 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2606 info
->typeattr
.cbAlignment
= 8;
2608 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2609 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2611 info
->typeattr
.cbAlignment
= sizeof(void*);
2614 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2615 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2616 info
->typeattr
.typekind
== TKIND_COCLASS
){
2617 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2618 info
->typeattr
.cbAlignment
= sizeof(void*);
2624 * process a typeinfo record
2626 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2629 ITypeLibImpl
* pLibInfo
)
2631 MSFT_TypeInfoBase tiBase
;
2632 ITypeInfoImpl
*ptiRet
;
2634 TRACE_(typelib
)("count=%u\n", count
);
2636 ptiRet
= ITypeInfoImpl_Constructor();
2637 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2638 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2640 /* this is where we are coming from */
2641 ptiRet
->pTypeLib
= pLibInfo
;
2642 ptiRet
->index
=count
;
2644 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2645 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2646 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2647 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2648 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2649 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2650 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2651 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2652 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2653 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2654 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2655 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2656 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2657 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2659 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2660 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2661 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2665 /* IDLDESC idldescType; *//* never saw this one != zero */
2667 /* name, eventually add to a hash table */
2668 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2669 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2670 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2672 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2673 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2674 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2676 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2677 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2679 /* note: InfoType's Help file and HelpStringDll come from the containing
2680 * library. Further HelpString and Docstring appear to be the same thing :(
2683 if(ptiRet
->typeattr
.cFuncs
>0 )
2684 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2685 ptiRet
->typeattr
.cVars
,
2686 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2688 if(ptiRet
->typeattr
.cVars
>0 )
2689 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2690 ptiRet
->typeattr
.cVars
,
2691 tiBase
.memoffset
, &ptiRet
->vardescs
);
2692 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2693 switch(ptiRet
->typeattr
.typekind
)
2696 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2699 case TKIND_DISPATCH
:
2700 /* This is not -1 when the interface is a non-base dual interface or
2701 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2702 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2706 if (tiBase
.datatype1
!= -1)
2708 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2709 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2713 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2714 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2718 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2720 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2721 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2722 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2723 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2724 if (TRACE_ON(typelib
))
2725 dump_TypeInfo(ptiRet
);
2730 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2733 INT16 len_str
, len_piece
;
2734 int offs
= 0, lengthInChars
;
2736 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2740 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2743 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2744 len_piece
= len_str
+ sizeof(INT16
);
2746 len_piece
= (len_piece
+ 4) & ~0x3;
2750 string
= heap_alloc(len_piece
+ 1);
2751 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2752 string
[len_str
] = '\0';
2754 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2755 string
, -1, NULL
, 0);
2756 if (!lengthInChars
) {
2758 return E_UNEXPECTED
;
2761 tlbstr
= heap_alloc(sizeof(TLBString
));
2763 tlbstr
->offset
= offs
;
2764 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2765 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2769 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2775 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2780 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2781 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2782 MSFT_ImpInfo impinfo
;
2785 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2787 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2788 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2790 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2791 if(pImpLib
->offset
==impinfo
.oImpFile
)
2794 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2795 ref
->reference
= offs
;
2796 ref
->pImpTLInfo
= pImpLib
;
2797 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2798 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2799 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2800 ref
->index
= TLB_REF_USE_GUID
;
2802 ref
->index
= impinfo
.oGuid
;
2804 ERR("Cannot find a reference\n");
2805 ref
->reference
= -1;
2806 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2809 offs
+= sizeof(impinfo
);
2815 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2816 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2817 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2820 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2821 static CRITICAL_SECTION cache_section
;
2822 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2824 0, 0, &cache_section
,
2825 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2826 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2828 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2831 typedef struct TLB_PEFile
2833 IUnknown IUnknown_iface
;
2836 HRSRC typelib_resource
;
2837 HGLOBAL typelib_global
;
2838 LPVOID typelib_base
;
2841 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2843 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2846 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2848 if (IsEqualIID(riid
, &IID_IUnknown
))
2851 IUnknown_AddRef(iface
);
2855 return E_NOINTERFACE
;
2858 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2860 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2861 return InterlockedIncrement(&This
->refs
);
2864 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2866 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2867 ULONG refs
= InterlockedDecrement(&This
->refs
);
2870 if (This
->typelib_global
)
2871 FreeResource(This
->typelib_global
);
2873 FreeLibrary(This
->dll
);
2879 static const IUnknownVtbl TLB_PEFile_Vtable
=
2881 TLB_PEFile_QueryInterface
,
2886 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2889 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2891 This
= heap_alloc(sizeof(TLB_PEFile
));
2893 return E_OUTOFMEMORY
;
2895 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2898 This
->typelib_resource
= NULL
;
2899 This
->typelib_global
= NULL
;
2900 This
->typelib_base
= NULL
;
2902 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2903 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2907 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2908 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2909 if (This
->typelib_resource
)
2911 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2912 if (This
->typelib_global
)
2914 This
->typelib_base
= LockResource(This
->typelib_global
);
2916 if (This
->typelib_base
)
2918 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2919 *ppBase
= This
->typelib_base
;
2920 *ppFile
= &This
->IUnknown_iface
;
2926 TRACE("No TYPELIB resource found\n");
2930 TLB_PEFile_Release(&This
->IUnknown_iface
);
2934 typedef struct TLB_NEFile
2936 IUnknown IUnknown_iface
;
2938 LPVOID typelib_base
;
2941 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2943 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2946 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2948 if (IsEqualIID(riid
, &IID_IUnknown
))
2951 IUnknown_AddRef(iface
);
2955 return E_NOINTERFACE
;
2958 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2960 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2961 return InterlockedIncrement(&This
->refs
);
2964 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2966 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2967 ULONG refs
= InterlockedDecrement(&This
->refs
);
2970 heap_free(This
->typelib_base
);
2976 static const IUnknownVtbl TLB_NEFile_Vtable
=
2978 TLB_NEFile_QueryInterface
,
2983 /***********************************************************************
2984 * read_xx_header [internal]
2986 static int read_xx_header( HFILE lzfd
)
2988 IMAGE_DOS_HEADER mzh
;
2991 LZSeek( lzfd
, 0, SEEK_SET
);
2992 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
2994 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
2997 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2998 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3001 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3003 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3004 return IMAGE_OS2_SIGNATURE
;
3005 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3006 return IMAGE_NT_SIGNATURE
;
3009 WARN("Can't handle %s files.\n", magic
);
3014 /***********************************************************************
3015 * find_ne_resource [internal]
3017 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3018 DWORD
*resLen
, DWORD
*resOff
)
3020 IMAGE_OS2_HEADER nehd
;
3021 NE_TYPEINFO
*typeInfo
;
3022 NE_NAMEINFO
*nameInfo
;
3028 /* Read in NE header */
3029 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3030 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3032 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3035 TRACE("No resources in NE dll\n" );
3039 /* Read in resource table */
3040 resTab
= heap_alloc( resTabSize
);
3041 if ( !resTab
) return FALSE
;
3043 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3044 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3046 heap_free( resTab
);
3051 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3053 if (!IS_INTRESOURCE(typeid)) /* named type */
3055 BYTE len
= strlen( typeid );
3056 while (typeInfo
->type_id
)
3058 if (!(typeInfo
->type_id
& 0x8000))
3060 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3061 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
3063 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3064 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3067 else /* numeric type id */
3069 WORD id
= LOWORD(typeid) | 0x8000;
3070 while (typeInfo
->type_id
)
3072 if (typeInfo
->type_id
== id
) goto found_type
;
3073 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3074 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3077 TRACE("No typeid entry found for %p\n", typeid );
3078 heap_free( resTab
);
3082 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3084 if (!IS_INTRESOURCE(resid
)) /* named resource */
3086 BYTE len
= strlen( resid
);
3087 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3089 BYTE
*p
= resTab
+ nameInfo
->id
;
3090 if (nameInfo
->id
& 0x8000) continue;
3091 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3094 else /* numeric resource id */
3096 WORD id
= LOWORD(resid
) | 0x8000;
3097 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3098 if (nameInfo
->id
== id
) goto found_name
;
3100 TRACE("No resid entry found for %p\n", typeid );
3101 heap_free( resTab
);
3105 /* Return resource data */
3106 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3107 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3109 heap_free( resTab
);
3113 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3117 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3120 This
= heap_alloc(sizeof(TLB_NEFile
));
3121 if (!This
) return E_OUTOFMEMORY
;
3123 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3125 This
->typelib_base
= NULL
;
3127 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3128 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3130 DWORD reslen
, offset
;
3131 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3133 This
->typelib_base
= heap_alloc(reslen
);
3134 if( !This
->typelib_base
)
3138 LZSeek( lzfd
, offset
, SEEK_SET
);
3139 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3141 *ppBase
= This
->typelib_base
;
3142 *pdwTLBLength
= reslen
;
3143 *ppFile
= &This
->IUnknown_iface
;
3149 if( lzfd
>= 0) LZClose( lzfd
);
3150 TLB_NEFile_Release(&This
->IUnknown_iface
);
3154 typedef struct TLB_Mapping
3156 IUnknown IUnknown_iface
;
3160 LPVOID typelib_base
;
3163 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3165 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3168 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3170 if (IsEqualIID(riid
, &IID_IUnknown
))
3173 IUnknown_AddRef(iface
);
3177 return E_NOINTERFACE
;
3180 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3182 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3183 return InterlockedIncrement(&This
->refs
);
3186 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3188 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3189 ULONG refs
= InterlockedDecrement(&This
->refs
);
3192 if (This
->typelib_base
)
3193 UnmapViewOfFile(This
->typelib_base
);
3195 CloseHandle(This
->mapping
);
3196 if (This
->file
!= INVALID_HANDLE_VALUE
)
3197 CloseHandle(This
->file
);
3203 static const IUnknownVtbl TLB_Mapping_Vtable
=
3205 TLB_Mapping_QueryInterface
,
3210 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3214 This
= heap_alloc(sizeof(TLB_Mapping
));
3216 return E_OUTOFMEMORY
;
3218 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3220 This
->file
= INVALID_HANDLE_VALUE
;
3221 This
->mapping
= NULL
;
3222 This
->typelib_base
= NULL
;
3224 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3225 if (INVALID_HANDLE_VALUE
!= This
->file
)
3227 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3230 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3231 if(This
->typelib_base
)
3233 /* retrieve file size */
3234 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3235 *ppBase
= This
->typelib_base
;
3236 *ppFile
= &This
->IUnknown_iface
;
3242 IUnknown_Release(&This
->IUnknown_iface
);
3243 return TYPE_E_CANTLOADLIBRARY
;
3246 /****************************************************************************
3249 * find the type of the typelib file and map the typelib resource into
3253 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3254 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3256 ITypeLibImpl
*entry
;
3259 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3260 LPVOID pBase
= NULL
;
3261 DWORD dwTLBLength
= 0;
3262 IUnknown
*pFile
= NULL
;
3267 index_str
= strrchrW(pszFileName
, '\\');
3268 if(index_str
&& *++index_str
!= '\0')
3271 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3272 if(*end_ptr
== '\0')
3274 int str_len
= index_str
- pszFileName
- 1;
3276 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3277 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3282 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3284 if(strchrW(file
, '\\'))
3286 lstrcpyW(pszPath
, file
);
3290 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3291 pszPath
[len
] = '\\';
3292 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3296 if(file
!= pszFileName
) heap_free(file
);
3298 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3299 if(h
!= INVALID_HANDLE_VALUE
){
3300 FILE_NAME_INFORMATION size_info
;
3303 /* GetFileInformationByHandleEx returns the path of the file without
3304 * WOW64 redirection */
3305 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, &size_info
, sizeof(size_info
));
3306 if(br
|| GetLastError() == ERROR_MORE_DATA
){
3307 FILE_NAME_INFORMATION
*info
;
3308 DWORD size
= sizeof(*info
) + size_info
.FileNameLength
+ sizeof(WCHAR
);
3310 info
= HeapAlloc(GetProcessHeap(), 0, size
);
3312 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, info
, size
);
3314 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3315 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3318 HeapFree(GetProcessHeap(), 0, info
);
3324 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3326 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3327 EnterCriticalSection(&cache_section
);
3328 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3330 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3332 TRACE("cache hit\n");
3333 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3334 ITypeLib2_AddRef(*ppTypeLib
);
3335 LeaveCriticalSection(&cache_section
);
3339 LeaveCriticalSection(&cache_section
);
3341 /* now actually load and parse the typelib */
3343 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3344 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3345 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3346 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3347 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3350 if (dwTLBLength
>= 4)
3352 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3353 if (dwSignature
== MSFT_SIGNATURE
)
3354 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3355 else if (dwSignature
== SLTG_SIGNATURE
)
3356 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3359 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3360 ret
= TYPE_E_CANTLOADLIBRARY
;
3364 ret
= TYPE_E_CANTLOADLIBRARY
;
3365 IUnknown_Release(pFile
);
3369 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3371 TRACE("adding to cache\n");
3372 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3373 lstrcpyW(impl
->path
, pszPath
);
3374 /* We should really canonicalise the path here. */
3375 impl
->index
= index
;
3377 /* FIXME: check if it has added already in the meantime */
3378 EnterCriticalSection(&cache_section
);
3379 list_add_head(&tlb_cache
, &impl
->entry
);
3380 LeaveCriticalSection(&cache_section
);
3386 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3388 ret
= TYPE_E_CANTLOADLIBRARY
;
3395 /*================== ITypeLib(2) Methods ===================================*/
3397 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3399 ITypeLibImpl
* pTypeLibImpl
;
3401 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3402 if (!pTypeLibImpl
) return NULL
;
3404 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3405 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3406 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3407 pTypeLibImpl
->ref
= 1;
3409 list_init(&pTypeLibImpl
->implib_list
);
3410 list_init(&pTypeLibImpl
->custdata_list
);
3411 list_init(&pTypeLibImpl
->name_list
);
3412 list_init(&pTypeLibImpl
->string_list
);
3413 list_init(&pTypeLibImpl
->guid_list
);
3414 list_init(&pTypeLibImpl
->ref_list
);
3415 pTypeLibImpl
->dispatch_href
= -1;
3417 return pTypeLibImpl
;
3420 /****************************************************************************
3421 * ITypeLib2_Constructor_MSFT
3423 * loading an MSFT typelib from an in-memory image
3425 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3429 MSFT_Header tlbHeader
;
3430 MSFT_SegDir tlbSegDir
;
3431 ITypeLibImpl
* pTypeLibImpl
;
3434 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3436 pTypeLibImpl
= TypeLibImpl_Constructor();
3437 if (!pTypeLibImpl
) return NULL
;
3439 /* get pointer to beginning of typelib data */
3443 cx
.pLibInfo
= pTypeLibImpl
;
3444 cx
.length
= dwTLBLength
;
3447 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3448 TRACE_(typelib
)("header:\n");
3449 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3450 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3451 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3454 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3456 /* there is a small amount of information here until the next important
3458 * the segment directory . Try to calculate the amount of data */
3459 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3461 /* now read the segment directory */
3462 TRACE("read segment directory (at %d)\n",lPSegDir
);
3463 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3464 cx
.pTblDir
= &tlbSegDir
;
3466 /* just check two entries */
3467 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3469 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3470 heap_free(pTypeLibImpl
);
3474 MSFT_ReadAllNames(&cx
);
3475 MSFT_ReadAllStrings(&cx
);
3476 MSFT_ReadAllGuids(&cx
);
3478 /* now fill our internal data */
3479 /* TLIBATTR fields */
3480 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3482 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3483 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3484 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3485 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3486 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3488 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3489 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3491 /* name, eventually add to a hash table */
3492 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3495 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3496 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3498 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3501 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3502 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3505 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3508 if(tlbHeader
.CustomDataOffset
>= 0)
3510 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3513 /* fill in type descriptions */
3514 if(tlbSegDir
.pTypdescTab
.length
> 0)
3516 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3518 pTypeLibImpl
->ctTypeDesc
= cTD
;
3519 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3520 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3523 /* FIXME: add several sanity checks here */
3524 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3525 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3527 /* FIXME: check safearray */
3529 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3531 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3533 else if(td
[0] == VT_CARRAY
)
3535 /* array descr table here */
3536 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3538 else if(td
[0] == VT_USERDEFINED
)
3540 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3542 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3545 /* second time around to fill the array subscript info */
3548 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3549 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3551 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3552 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3555 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3557 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3559 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3561 for(j
= 0; j
<td
[2]; j
++)
3563 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3564 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3565 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3566 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3571 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3572 ERR("didn't find array description data\n");
3577 /* imported type libs */
3578 if(tlbSegDir
.pImpFiles
.offset
>0)
3581 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3584 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3588 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3589 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3590 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3592 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3593 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3594 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3595 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3598 name
= heap_alloc_zero(size
+1);
3599 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3600 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3603 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3604 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3606 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3610 MSFT_ReadAllRefs(&cx
);
3612 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3615 if(tlbHeader
.nrtypeinfos
>= 0 )
3617 ITypeInfoImpl
**ppTI
;
3619 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3621 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3623 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3626 (pTypeLibImpl
->TypeInfoCount
)++;
3631 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3632 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3633 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3637 TRACE("(%p)\n", pTypeLibImpl
);
3638 return &pTypeLibImpl
->ITypeLib2_iface
;
3642 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3648 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3649 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3653 guid
->Data4
[0] = s
>> 8;
3654 guid
->Data4
[1] = s
& 0xff;
3657 for(i
= 0; i
< 6; i
++) {
3658 memcpy(b
, str
+ 24 + 2 * i
, 2);
3659 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3664 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3671 bytelen
= *(const WORD
*)ptr
;
3672 if(bytelen
== 0xffff) return 2;
3674 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3675 tmp_str
= SysAllocStringLen(NULL
, len
);
3677 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3678 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3679 SysFreeString(tmp_str
);
3684 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3689 bytelen
= *(const WORD
*)ptr
;
3690 if(bytelen
== 0xffff) return 2;
3691 *str
= heap_alloc(bytelen
+ 1);
3692 memcpy(*str
, ptr
+ 2, bytelen
);
3693 (*str
)[bytelen
] = '\0';
3697 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3702 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3703 if (tlbstr
->offset
== offset
)
3707 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3708 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3709 SysFreeString(tmp_str
);
3714 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3716 char *ptr
= pLibBlk
;
3719 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3720 FIXME("libblk magic = %04x\n", w
);
3725 if((w
= *(WORD
*)ptr
) != 0xffff) {
3726 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3731 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3733 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3735 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3738 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3739 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3742 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3743 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3745 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3748 ptr
+= 4; /* skip res12 */
3750 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3753 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3756 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3759 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3760 ptr
+= sizeof(GUID
);
3762 return ptr
- (char*)pLibBlk
;
3765 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3770 } sltg_ref_lookup_t
;
3772 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3773 HREFTYPE
*typelib_ref
)
3775 if(table
&& typeinfo_ref
< table
->num
)
3777 *typelib_ref
= table
->refs
[typeinfo_ref
];
3781 ERR_(typelib
)("Unable to find reference\n");
3786 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3791 if((*pType
& 0xe00) == 0xe00) {
3793 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3794 pTD
= pTD
->u
.lptdesc
;
3796 switch(*pType
& 0x3f) {
3799 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3800 pTD
= pTD
->u
.lptdesc
;
3803 case VT_USERDEFINED
:
3804 pTD
->vt
= VT_USERDEFINED
;
3805 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3811 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3814 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3816 pTD
->vt
= VT_CARRAY
;
3817 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3818 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3819 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3820 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3822 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3828 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3832 pTD
->vt
= VT_SAFEARRAY
;
3833 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3834 pTD
= pTD
->u
.lptdesc
;
3838 pTD
->vt
= *pType
& 0x3f;
3847 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3848 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3850 /* Handle [in/out] first */
3851 if((*pType
& 0xc000) == 0xc000)
3852 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3853 else if(*pType
& 0x8000)
3854 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3855 else if(*pType
& 0x4000)
3856 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3858 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3861 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3864 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3866 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3870 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3875 TLBRefType
*ref_type
;
3876 sltg_ref_lookup_t
*table
;
3877 HREFTYPE typelib_ref
;
3879 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3880 FIXME("Ref magic = %x\n", pRef
->magic
);
3883 name
= ( (char*)pRef
->names
+ pRef
->number
);
3885 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3886 table
->num
= pRef
->number
>> 3;
3888 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3890 /* We don't want the first href to be 0 */
3891 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3893 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3895 unsigned int lib_offs
, type_num
;
3897 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3899 name
+= SLTG_ReadStringA(name
, &refname
);
3900 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3901 FIXME_(typelib
)("Can't sscanf ref\n");
3902 if(lib_offs
!= 0xffff) {
3905 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3906 if(import
->offset
== lib_offs
)
3909 if(&import
->entry
== &pTL
->implib_list
) {
3910 char fname
[MAX_PATH
+1];
3914 import
= heap_alloc_zero(sizeof(*import
));
3915 import
->offset
= lib_offs
;
3916 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3917 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3918 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3919 &import
->wVersionMajor
,
3920 &import
->wVersionMinor
,
3921 &import
->lcid
, fname
) != 4) {
3922 FIXME_(typelib
)("can't sscanf ref %s\n",
3923 pNameTable
+ lib_offs
+ 40);
3925 len
= strlen(fname
);
3926 if(fname
[len
-1] != '#')
3927 FIXME("fname = %s\n", fname
);
3928 fname
[len
-1] = '\0';
3929 import
->name
= TLB_MultiByteToBSTR(fname
);
3930 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3932 ref_type
->pImpTLInfo
= import
;
3934 /* Store a reference to IDispatch */
3935 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3936 pTL
->dispatch_href
= typelib_ref
;
3938 } else { /* internal ref */
3939 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3941 ref_type
->reference
= typelib_ref
;
3942 ref_type
->index
= type_num
;
3945 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3947 table
->refs
[ref
] = typelib_ref
;
3950 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3951 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3952 dump_TLBRefType(pTL
);
3956 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3957 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3959 SLTG_ImplInfo
*info
;
3960 TLBImplType
*pImplType
;
3961 /* I don't really get this structure, usually it's 0x16 bytes
3962 long, but iuser.tlb contains some that are 0x18 bytes long.
3963 That's ok because we can use the next ptr to jump to the next
3964 one. But how do we know the length of the last one? The WORD
3965 at offs 0x8 might be the clue. For now I'm just assuming that
3966 the last one is the regular 0x16 bytes. */
3968 info
= (SLTG_ImplInfo
*)pBlk
;
3970 pTI
->typeattr
.cImplTypes
++;
3971 if(info
->next
== 0xffff)
3973 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3976 info
= (SLTG_ImplInfo
*)pBlk
;
3977 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
3978 pImplType
= pTI
->impltypes
;
3980 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3981 pImplType
->implflags
= info
->impltypeflags
;
3984 if(info
->next
== 0xffff)
3987 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3988 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3990 info
++; /* see comment at top of function */
3994 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
3995 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3997 TLBVarDesc
*pVarDesc
;
3998 const TLBString
*prevName
= NULL
;
3999 SLTG_Variable
*pItem
;
4003 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4005 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4006 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4008 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4010 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4011 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4012 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4016 if (pItem
->name
== 0xfffe)
4017 pVarDesc
->Name
= prevName
;
4019 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4021 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4022 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4023 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4025 if(pItem
->flags
& 0x02)
4026 pType
= &pItem
->type
;
4028 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4030 if (pItem
->flags
& ~0xda)
4031 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4033 SLTG_DoElem(pType
, pBlk
,
4034 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4036 if (TRACE_ON(typelib
)) {
4038 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4039 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4042 if (pItem
->flags
& 0x40) {
4043 TRACE_(typelib
)("VAR_DISPATCH\n");
4044 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4046 else if (pItem
->flags
& 0x10) {
4047 TRACE_(typelib
)("VAR_CONST\n");
4048 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4049 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4050 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4051 if (pItem
->flags
& 0x08)
4052 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4054 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4060 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4062 TRACE_(typelib
)("len = %u\n", len
);
4063 if (len
== 0xffff) {
4066 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4067 str
= SysAllocStringLen(NULL
, alloc_len
);
4068 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4070 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4071 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4080 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4081 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4084 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4089 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4090 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4091 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4094 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4095 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4097 if (pItem
->flags
& 0x80)
4098 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4100 prevName
= pVarDesc
->Name
;
4102 pTI
->typeattr
.cVars
= cVars
;
4105 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4106 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4108 SLTG_Function
*pFunc
;
4110 TLBFuncDesc
*pFuncDesc
;
4112 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4114 pFuncDesc
= pTI
->funcdescs
;
4115 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4116 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4121 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4122 case SLTG_FUNCTION_MAGIC
:
4123 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4125 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4126 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4128 case SLTG_STATIC_FUNCTION_MAGIC
:
4129 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4132 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4135 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4137 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4138 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4139 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4140 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4141 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4142 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4144 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4145 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4147 if(pFunc
->retnextopt
& 0x80)
4148 pType
= &pFunc
->rettype
;
4150 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4152 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4154 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4155 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4156 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4158 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4160 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4161 char *paramName
= pNameTable
+ *pArg
;
4163 /* If arg type follows then paramName points to the 2nd
4164 letter of the name, else the next WORD is an offset to
4165 the arg type and paramName points to the first letter.
4166 So let's take one char off paramName and see if we're
4167 pointing at an alpha-numeric char. However if *pArg is
4168 0xffff or 0xfffe then the param has no name, the former
4169 meaning that the next WORD is the type, the latter
4170 meaning that the next WORD is an offset to the type. */
4175 else if(*pArg
== 0xfffe) {
4179 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4184 if(HaveOffs
) { /* the next word is an offset to type */
4185 pType
= (WORD
*)(pBlk
+ *pArg
);
4186 SLTG_DoElem(pType
, pBlk
,
4187 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4192 pArg
= SLTG_DoElem(pArg
, pBlk
,
4193 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4196 /* Are we an optional param ? */
4197 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4198 pFuncDesc
->funcdesc
.cParamsOpt
)
4199 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4202 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4203 paramName
- pNameTable
, pTI
->pTypeLib
);
4205 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4209 pTI
->typeattr
.cFuncs
= cFuncs
;
4212 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4213 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4214 SLTG_TypeInfoTail
*pTITail
)
4217 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4219 if(pTIHeader
->href_table
!= 0xffffffff) {
4220 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4226 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4227 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4229 heap_free(ref_lookup
);
4233 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4234 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4235 const SLTG_TypeInfoTail
*pTITail
)
4238 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4240 if(pTIHeader
->href_table
!= 0xffffffff) {
4241 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4247 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4248 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4251 if (pTITail
->funcs_off
!= 0xffff)
4252 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4254 heap_free(ref_lookup
);
4256 if (TRACE_ON(typelib
))
4257 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4260 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4261 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4262 const SLTG_TypeInfoTail
*pTITail
)
4264 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4267 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4268 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4269 const SLTG_TypeInfoTail
*pTITail
)
4272 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4274 if (pTITail
->simple_alias
) {
4275 /* if simple alias, no more processing required */
4276 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4277 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4281 if(pTIHeader
->href_table
!= 0xffffffff) {
4282 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4286 /* otherwise it is an offset to a type */
4287 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4289 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4290 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4292 heap_free(ref_lookup
);
4295 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4296 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4297 const SLTG_TypeInfoTail
*pTITail
)
4299 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4300 if (pTIHeader
->href_table
!= 0xffffffff)
4301 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4304 if (pTITail
->vars_off
!= 0xffff)
4305 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4307 if (pTITail
->funcs_off
!= 0xffff)
4308 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4310 if (pTITail
->impls_off
!= 0xffff)
4311 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4313 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4314 * of dispinterface functions including the IDispatch ones, so
4315 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4316 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4318 heap_free(ref_lookup
);
4319 if (TRACE_ON(typelib
))
4320 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4323 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4324 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4325 const SLTG_TypeInfoTail
*pTITail
)
4327 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4330 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4331 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4332 const SLTG_TypeInfoTail
*pTITail
)
4334 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4335 if (pTIHeader
->href_table
!= 0xffffffff)
4336 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4339 if (pTITail
->vars_off
!= 0xffff)
4340 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4342 if (pTITail
->funcs_off
!= 0xffff)
4343 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4344 heap_free(ref_lookup
);
4345 if (TRACE_ON(typelib
))
4349 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4350 manageable copy of it into this */
4363 } SLTG_InternalOtherTypeInfo
;
4365 /****************************************************************************
4366 * ITypeLib2_Constructor_SLTG
4368 * loading a SLTG typelib from an in-memory image
4370 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4372 ITypeLibImpl
*pTypeLibImpl
;
4373 SLTG_Header
*pHeader
;
4374 SLTG_BlkEntry
*pBlkEntry
;
4378 LPVOID pBlk
, pFirstBlk
;
4379 SLTG_LibBlk
*pLibBlk
;
4380 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4381 char *pAfterOTIBlks
= NULL
;
4382 char *pNameTable
, *ptr
;
4385 ITypeInfoImpl
**ppTypeInfoImpl
;
4387 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4390 pTypeLibImpl
= TypeLibImpl_Constructor();
4391 if (!pTypeLibImpl
) return NULL
;
4395 TRACE_(typelib
)("header:\n");
4396 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4397 pHeader
->nrOfFileBlks
);
4398 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4399 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4400 pHeader
->SLTG_magic
);
4404 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4405 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4407 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4408 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4410 /* Next we have a magic block */
4411 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4413 /* Let's see if we're still in sync */
4414 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4415 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4416 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4419 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4420 sizeof(SLTG_DIR_MAGIC
))) {
4421 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4425 pIndex
= (SLTG_Index
*)(pMagic
+1);
4427 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4429 pFirstBlk
= pPad9
+ 1;
4431 /* We'll set up a ptr to the main library block, which is the last one. */
4433 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4434 pBlkEntry
[order
].next
!= 0;
4435 order
= pBlkEntry
[order
].next
- 1) {
4436 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4440 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4442 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4447 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4449 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4452 ptr
= (char*)pLibBlk
+ len
;
4454 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4458 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4460 w
= *(WORD
*)(ptr
+ 2);
4463 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4464 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4465 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4467 w
= *(WORD
*)(ptr
+ 4 + len
);
4469 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4471 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4472 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4473 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4475 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4476 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4477 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4479 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4480 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4483 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4484 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4485 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4486 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4487 len
+= sizeof(SLTG_OtherTypeInfo
);
4491 pAfterOTIBlks
= ptr
;
4493 /* Skip this WORD and get the next DWORD */
4494 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4496 /* Now add this to pLibBLk look at what we're pointing at and
4497 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4498 dust and we should be pointing at the beginning of the name
4501 pNameTable
= (char*)pLibBlk
+ len
;
4503 switch(*(WORD
*)pNameTable
) {
4510 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4514 pNameTable
+= 0x216;
4518 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4520 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4523 /* Hopefully we now have enough ptrs set up to actually read in
4524 some TypeInfos. It's not clear which order to do them in, so
4525 I'll just follow the links along the BlkEntry chain and read
4526 them in the order in which they are in the file */
4528 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4529 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4531 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4532 pBlkEntry
[order
].next
!= 0;
4533 order
= pBlkEntry
[order
].next
- 1, i
++) {
4535 SLTG_TypeInfoHeader
*pTIHeader
;
4536 SLTG_TypeInfoTail
*pTITail
;
4537 SLTG_MemberHeader
*pMemHeader
;
4539 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4540 FIXME_(typelib
)("Index strings don't match\n");
4541 heap_free(pOtherTypeInfoBlks
);
4546 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4547 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4548 heap_free(pOtherTypeInfoBlks
);
4551 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4552 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4553 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4555 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4556 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4557 (*ppTypeInfoImpl
)->index
= i
;
4558 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4559 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4560 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4561 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4562 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4563 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4564 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4565 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4567 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4568 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4570 if((pTIHeader
->typeflags1
& 7) != 2)
4571 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4572 if(pTIHeader
->typeflags3
!= 2)
4573 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4575 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4576 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4577 typekind_desc
[pTIHeader
->typekind
],
4578 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4579 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4581 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4583 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4585 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4586 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4587 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4589 switch(pTIHeader
->typekind
) {
4591 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4592 pTIHeader
, pTITail
);
4596 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4597 pTIHeader
, pTITail
);
4600 case TKIND_INTERFACE
:
4601 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4602 pTIHeader
, pTITail
);
4606 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4607 pTIHeader
, pTITail
);
4611 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4612 pTIHeader
, pTITail
);
4615 case TKIND_DISPATCH
:
4616 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4617 pTIHeader
, pTITail
);
4621 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4622 pTIHeader
, pTITail
);
4626 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4631 /* could get cFuncs, cVars and cImplTypes from here
4632 but we've already set those */
4633 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4649 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4652 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4653 FIXME("Somehow processed %d TypeInfos\n", i
);
4654 heap_free(pOtherTypeInfoBlks
);
4658 heap_free(pOtherTypeInfoBlks
);
4659 return &pTypeLibImpl
->ITypeLib2_iface
;
4662 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4664 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4666 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4668 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4669 IsEqualIID(riid
,&IID_ITypeLib
)||
4670 IsEqualIID(riid
,&IID_ITypeLib2
))
4672 *ppv
= &This
->ITypeLib2_iface
;
4674 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4675 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4677 *ppv
= &This
->ICreateTypeLib2_iface
;
4682 TRACE("-- Interface: E_NOINTERFACE\n");
4683 return E_NOINTERFACE
;
4686 IUnknown_AddRef((IUnknown
*)*ppv
);
4690 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4692 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4693 ULONG ref
= InterlockedIncrement(&This
->ref
);
4695 TRACE("(%p) ref=%u\n", This
, ref
);
4700 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4702 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4703 ULONG ref
= InterlockedDecrement(&This
->ref
);
4705 TRACE("(%p) ref=%u\n",This
, ref
);
4709 TLBImpLib
*pImpLib
, *pImpLibNext
;
4710 TLBRefType
*ref_type
, *ref_type_next
;
4711 TLBString
*tlbstr
, *tlbstr_next
;
4712 TLBGuid
*tlbguid
, *tlbguid_next
;
4715 /* remove cache entry */
4718 TRACE("removing from cache list\n");
4719 EnterCriticalSection(&cache_section
);
4720 if(This
->entry
.next
)
4721 list_remove(&This
->entry
);
4722 LeaveCriticalSection(&cache_section
);
4723 heap_free(This
->path
);
4725 TRACE(" destroying ITypeLib(%p)\n",This
);
4727 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4728 list_remove(&tlbstr
->entry
);
4729 SysFreeString(tlbstr
->str
);
4733 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4734 list_remove(&tlbstr
->entry
);
4735 SysFreeString(tlbstr
->str
);
4739 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4740 list_remove(&tlbguid
->entry
);
4744 TLB_FreeCustData(&This
->custdata_list
);
4746 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4747 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4748 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4750 heap_free(This
->pTypeDesc
);
4752 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4754 if (pImpLib
->pImpTypeLib
)
4755 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4756 SysFreeString(pImpLib
->name
);
4758 list_remove(&pImpLib
->entry
);
4762 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, ref_type_next
, &This
->ref_list
, TLBRefType
, entry
)
4764 list_remove(&ref_type
->entry
);
4765 heap_free(ref_type
);
4768 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4769 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4770 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4772 heap_free(This
->typeinfos
);
4780 /* ITypeLib::GetTypeInfoCount
4782 * Returns the number of type descriptions in the type library
4784 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4786 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4787 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4788 return This
->TypeInfoCount
;
4791 /* ITypeLib::GetTypeInfo
4793 * retrieves the specified type description in the library.
4795 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4798 ITypeInfo
**ppTInfo
)
4800 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4802 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4805 return E_INVALIDARG
;
4807 if(index
>= This
->TypeInfoCount
)
4808 return TYPE_E_ELEMENTNOTFOUND
;
4810 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4811 ITypeInfo_AddRef(*ppTInfo
);
4817 /* ITypeLibs::GetTypeInfoType
4819 * Retrieves the type of a type description.
4821 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4826 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4828 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4831 return E_INVALIDARG
;
4833 if(index
>= This
->TypeInfoCount
)
4834 return TYPE_E_ELEMENTNOTFOUND
;
4836 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4841 /* ITypeLib::GetTypeInfoOfGuid
4843 * Retrieves the type description that corresponds to the specified GUID.
4846 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4849 ITypeInfo
**ppTInfo
)
4851 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4854 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4856 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4857 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4858 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4859 ITypeInfo_AddRef(*ppTInfo
);
4864 return TYPE_E_ELEMENTNOTFOUND
;
4867 /* ITypeLib::GetLibAttr
4869 * Retrieves the structure that contains the library's attributes.
4872 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4876 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4878 TRACE("(%p, %p)\n", This
, attr
);
4880 if (!attr
) return E_INVALIDARG
;
4882 *attr
= heap_alloc(sizeof(**attr
));
4883 if (!*attr
) return E_OUTOFMEMORY
;
4885 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4886 (*attr
)->lcid
= This
->set_lcid
;
4887 (*attr
)->syskind
= This
->syskind
;
4888 (*attr
)->wMajorVerNum
= This
->ver_major
;
4889 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4890 (*attr
)->wLibFlags
= This
->libflags
;
4895 /* ITypeLib::GetTypeComp
4897 * Enables a client compiler to bind to a library's types, variables,
4898 * constants, and global functions.
4901 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4903 ITypeComp
**ppTComp
)
4905 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4907 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4908 *ppTComp
= &This
->ITypeComp_iface
;
4909 ITypeComp_AddRef(*ppTComp
);
4914 /* ITypeLib::GetDocumentation
4916 * Retrieves the library's documentation string, the complete Help file name
4917 * and path, and the context identifier for the library Help topic in the Help
4920 * On a successful return all non-null BSTR pointers will have been set,
4923 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4927 BSTR
*pBstrDocString
,
4928 DWORD
*pdwHelpContext
,
4929 BSTR
*pBstrHelpFile
)
4931 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4932 HRESULT result
= E_INVALIDARG
;
4935 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4937 pBstrName
, pBstrDocString
,
4938 pdwHelpContext
, pBstrHelpFile
);
4942 /* documentation for the typelib */
4947 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4955 if (This
->DocString
)
4957 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4961 *pBstrDocString
= NULL
;
4965 *pdwHelpContext
= This
->dwHelpContext
;
4971 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
4975 *pBstrHelpFile
= NULL
;
4982 /* for a typeinfo */
4983 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4985 if(SUCCEEDED(result
))
4987 result
= ITypeInfo_GetDocumentation(pTInfo
,
4991 pdwHelpContext
, pBstrHelpFile
);
4993 ITypeInfo_Release(pTInfo
);
4998 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5000 if (pBstrName
) SysFreeString (*pBstrName
);
5002 return STG_E_INSUFFICIENTMEMORY
;
5007 * Indicates whether a passed-in string contains the name of a type or member
5008 * described in the library.
5011 static HRESULT WINAPI
ITypeLib2_fnIsName(
5017 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5019 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5021 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5025 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5026 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5027 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5028 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5029 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5031 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5032 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5033 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5034 goto ITypeLib2_fnIsName_exit
;
5037 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5038 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5039 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5045 ITypeLib2_fnIsName_exit
:
5046 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5047 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5052 /* ITypeLib::FindName
5054 * Finds occurrences of a type description in a type library. This may be used
5055 * to quickly verify that a name exists in a type library.
5058 static HRESULT WINAPI
ITypeLib2_fnFindName(
5062 ITypeInfo
**ppTInfo
,
5066 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5071 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5073 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5074 return E_INVALIDARG
;
5076 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5077 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5078 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5082 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5083 memid
[count
] = MEMBERID_NIL
;
5084 goto ITypeLib2_fnFindName_exit
;
5087 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5088 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5090 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5091 memid
[count
] = func
->funcdesc
.memid
;
5092 goto ITypeLib2_fnFindName_exit
;
5096 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->typeattr
.cVars
, name
);
5098 memid
[count
] = var
->vardesc
.memid
;
5099 goto ITypeLib2_fnFindName_exit
;
5103 ITypeLib2_fnFindName_exit
:
5104 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5105 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5108 TRACE("found %d typeinfos\n", count
);
5115 /* ITypeLib::ReleaseTLibAttr
5117 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5120 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5122 TLIBATTR
*pTLibAttr
)
5124 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5125 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5126 heap_free(pTLibAttr
);
5129 /* ITypeLib2::GetCustData
5131 * gets the custom data
5133 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5138 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5139 TLBCustData
*pCData
;
5141 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5143 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5145 return TYPE_E_ELEMENTNOTFOUND
;
5147 VariantInit(pVarVal
);
5148 VariantCopy(pVarVal
, &pCData
->data
);
5153 /* ITypeLib2::GetLibStatistics
5155 * Returns statistics about a type library that are required for efficient
5156 * sizing of hash tables.
5159 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5161 ULONG
*pcUniqueNames
,
5162 ULONG
*pcchUniqueNames
)
5164 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5166 FIXME("(%p): stub!\n", This
);
5168 if(pcUniqueNames
) *pcUniqueNames
=1;
5169 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5173 /* ITypeLib2::GetDocumentation2
5175 * Retrieves the library's documentation string, the complete Help file name
5176 * and path, the localization context to use, and the context ID for the
5177 * library Help topic in the Help file.
5180 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5184 BSTR
*pbstrHelpString
,
5185 DWORD
*pdwHelpStringContext
,
5186 BSTR
*pbstrHelpStringDll
)
5188 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5192 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5194 /* the help string should be obtained from the helpstringdll,
5195 * using the _DLLGetDocumentation function, based on the supplied
5196 * lcid. Nice to do sometime...
5200 /* documentation for the typelib */
5202 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5203 if(pdwHelpStringContext
)
5204 *pdwHelpStringContext
=This
->dwHelpContext
;
5205 if(pbstrHelpStringDll
)
5206 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5212 /* for a typeinfo */
5213 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5215 if(SUCCEEDED(result
))
5217 ITypeInfo2
* pTInfo2
;
5218 result
= ITypeInfo_QueryInterface(pTInfo
,
5220 (LPVOID
*) &pTInfo2
);
5222 if(SUCCEEDED(result
))
5224 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5228 pdwHelpStringContext
,
5229 pbstrHelpStringDll
);
5231 ITypeInfo2_Release(pTInfo2
);
5234 ITypeInfo_Release(pTInfo
);
5240 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5242 TLBCustData
*pCData
;
5246 ct
= list_count(custdata_list
);
5248 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5249 if(!pCustData
->prgCustData
)
5250 return E_OUTOFMEMORY
;
5252 pCustData
->cCustData
= ct
;
5254 cdi
= pCustData
->prgCustData
;
5255 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5256 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5257 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5265 /* ITypeLib2::GetAllCustData
5267 * Gets all custom data items for the library.
5270 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5272 CUSTDATA
*pCustData
)
5274 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5275 TRACE("(%p)->(%p)\n", This
, pCustData
);
5276 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5279 static const ITypeLib2Vtbl tlbvt
= {
5280 ITypeLib2_fnQueryInterface
,
5282 ITypeLib2_fnRelease
,
5283 ITypeLib2_fnGetTypeInfoCount
,
5284 ITypeLib2_fnGetTypeInfo
,
5285 ITypeLib2_fnGetTypeInfoType
,
5286 ITypeLib2_fnGetTypeInfoOfGuid
,
5287 ITypeLib2_fnGetLibAttr
,
5288 ITypeLib2_fnGetTypeComp
,
5289 ITypeLib2_fnGetDocumentation
,
5291 ITypeLib2_fnFindName
,
5292 ITypeLib2_fnReleaseTLibAttr
,
5294 ITypeLib2_fnGetCustData
,
5295 ITypeLib2_fnGetLibStatistics
,
5296 ITypeLib2_fnGetDocumentation2
,
5297 ITypeLib2_fnGetAllCustData
5301 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5303 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5305 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5308 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5310 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5312 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5315 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5317 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5319 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5322 static HRESULT WINAPI
ITypeLibComp_fnBind(
5327 ITypeInfo
** ppTInfo
,
5328 DESCKIND
* pDescKind
,
5331 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5332 BOOL typemismatch
= FALSE
;
5335 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5337 *pDescKind
= DESCKIND_NONE
;
5338 pBindPtr
->lptcomp
= NULL
;
5341 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5342 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5343 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5345 /* FIXME: check wFlags here? */
5346 /* FIXME: we should use a hash table to look this info up using lHash
5347 * instead of an O(n) search */
5348 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5349 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5351 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5353 *pDescKind
= DESCKIND_TYPECOMP
;
5354 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5355 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5356 TRACE("module or enum: %s\n", debugstr_w(szName
));
5361 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5362 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5364 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5367 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5368 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5370 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5373 else if (hr
== TYPE_E_TYPEMISMATCH
)
5374 typemismatch
= TRUE
;
5377 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5378 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5380 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5382 ITypeInfo
*subtypeinfo
;
5384 DESCKIND subdesckind
;
5386 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5387 &subtypeinfo
, &subdesckind
, &subbindptr
);
5388 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5390 TYPEDESC tdesc_appobject
;
5391 const VARDESC vardesc_appobject
=
5394 NULL
, /* lpstrSchema */
5409 VAR_STATIC
/* varkind */
5412 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5413 tdesc_appobject
.vt
= VT_USERDEFINED
;
5415 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5417 /* cleanup things filled in by Bind call so we can put our
5418 * application object data in there instead */
5419 switch (subdesckind
)
5421 case DESCKIND_FUNCDESC
:
5422 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5424 case DESCKIND_VARDESC
:
5425 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5430 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5432 if (pTypeInfo
->hreftype
== -1)
5433 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5435 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5439 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5440 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5441 ITypeInfo_AddRef(*ppTInfo
);
5444 else if (hr
== TYPE_E_TYPEMISMATCH
)
5445 typemismatch
= TRUE
;
5451 TRACE("type mismatch %s\n", debugstr_w(szName
));
5452 return TYPE_E_TYPEMISMATCH
;
5456 TRACE("name not found %s\n", debugstr_w(szName
));
5461 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5465 ITypeInfo
** ppTInfo
,
5466 ITypeComp
** ppTComp
)
5468 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5469 ITypeInfoImpl
*info
;
5471 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5473 if(!szName
|| !ppTInfo
|| !ppTComp
)
5474 return E_INVALIDARG
;
5476 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5483 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5484 ITypeInfo_AddRef(*ppTInfo
);
5485 *ppTComp
= &info
->ITypeComp_iface
;
5486 ITypeComp_AddRef(*ppTComp
);
5491 static const ITypeCompVtbl tlbtcvt
=
5494 ITypeLibComp_fnQueryInterface
,
5495 ITypeLibComp_fnAddRef
,
5496 ITypeLibComp_fnRelease
,
5498 ITypeLibComp_fnBind
,
5499 ITypeLibComp_fnBindType
5502 /*================== ITypeInfo(2) Methods ===================================*/
5503 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5505 ITypeInfoImpl
*pTypeInfoImpl
;
5507 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5510 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5511 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5512 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5513 pTypeInfoImpl
->ref
= 0;
5514 pTypeInfoImpl
->hreftype
= -1;
5515 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5516 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5517 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5518 list_init(pTypeInfoImpl
->pcustdata_list
);
5520 TRACE("(%p)\n", pTypeInfoImpl
);
5521 return pTypeInfoImpl
;
5524 /* ITypeInfo::QueryInterface
5526 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5531 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5533 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5536 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5537 IsEqualIID(riid
,&IID_ITypeInfo
)||
5538 IsEqualIID(riid
,&IID_ITypeInfo2
))
5539 *ppvObject
= &This
->ITypeInfo2_iface
;
5540 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5541 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5542 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5543 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5544 *ppvObject
= &This
->ITypeComp_iface
;
5547 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5548 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5551 TRACE("-- Interface: E_NOINTERFACE\n");
5552 return E_NOINTERFACE
;
5555 /* ITypeInfo::AddRef
5557 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5559 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5560 ULONG ref
= InterlockedIncrement(&This
->ref
);
5562 TRACE("(%p)->ref is %u\n",This
, ref
);
5564 if (ref
== 1 /* incremented from 0 */)
5565 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5570 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5574 TRACE("destroying ITypeInfo(%p)\n",This
);
5576 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5579 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5580 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5582 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5583 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5584 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5585 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5587 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5588 heap_free(pFInfo
->pParamDesc
);
5589 TLB_FreeCustData(&pFInfo
->custdata_list
);
5591 heap_free(This
->funcdescs
);
5593 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5595 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5596 if (pVInfo
->vardesc_create
) {
5597 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5598 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5599 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5600 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5602 TLB_FreeCustData(&pVInfo
->custdata_list
);
5604 heap_free(This
->vardescs
);
5606 if(This
->impltypes
){
5607 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5608 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5609 TLB_FreeCustData(&pImpl
->custdata_list
);
5611 heap_free(This
->impltypes
);
5614 TLB_FreeCustData(&This
->custdata_list
);
5619 /* ITypeInfo::Release
5621 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5623 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5624 ULONG ref
= InterlockedDecrement(&This
->ref
);
5626 TRACE("(%p)->(%u)\n",This
, ref
);
5630 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5631 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5632 if (not_attached_to_typelib
)
5634 /* otherwise This will be freed when typelib is freed */
5640 /* ITypeInfo::GetTypeAttr
5642 * Retrieves a TYPEATTR structure that contains the attributes of the type
5646 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5647 LPTYPEATTR
*ppTypeAttr
)
5649 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5652 TRACE("(%p)\n",This
);
5654 size
= sizeof(**ppTypeAttr
);
5655 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5656 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5658 *ppTypeAttr
= heap_alloc(size
);
5660 return E_OUTOFMEMORY
;
5662 **ppTypeAttr
= This
->typeattr
;
5663 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5665 if (This
->tdescAlias
)
5666 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5668 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5669 /* This should include all the inherited funcs */
5670 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5671 /* This is always the size of IDispatch's vtbl */
5672 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5673 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5678 /* ITypeInfo::GetTypeComp
5680 * Retrieves the ITypeComp interface for the type description, which enables a
5681 * client compiler to bind to the type description's members.
5684 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5685 ITypeComp
* *ppTComp
)
5687 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5689 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5691 *ppTComp
= &This
->ITypeComp_iface
;
5692 ITypeComp_AddRef(*ppTComp
);
5696 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5698 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5699 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5700 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5704 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5707 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5708 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5710 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5711 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5712 *buffer
+= sizeof(PARAMDESCEX
);
5713 *pparamdescex_dest
= *pparamdescex_src
;
5714 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5715 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5716 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5717 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5720 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5724 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5726 UINT len
= SysStringLen(str
), i
;
5727 for (i
= 0; i
< len
; ++i
)
5733 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5735 if (V_VT(var
) == VT_INT
)
5736 return VariantChangeType(var
, var
, 0, VT_I4
);
5737 else if (V_VT(var
) == VT_UINT
)
5738 return VariantChangeType(var
, var
, 0, VT_UI4
);
5739 else if (V_VT(var
) == VT_BSTR
)
5740 return TLB_SanitizeBSTR(V_BSTR(var
));
5745 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5747 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5748 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5751 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5755 SIZE_T size
= sizeof(*src
);
5759 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5760 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5761 for (i
= 0; i
< src
->cParams
; i
++)
5763 size
+= sizeof(ELEMDESC
);
5764 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5767 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5768 if (!dest
) return E_OUTOFMEMORY
;
5771 if (dispinterface
) /* overwrite funckind */
5772 dest
->funckind
= FUNC_DISPATCH
;
5773 buffer
= (char *)(dest
+ 1);
5775 dest
->oVft
= dest
->oVft
& 0xFFFC;
5777 if (dest
->cScodes
) {
5778 dest
->lprgscode
= (SCODE
*)buffer
;
5779 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5780 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5782 dest
->lprgscode
= NULL
;
5784 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5787 SysFreeString((BSTR
)dest
);
5791 if (dest
->cParams
) {
5792 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5793 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5794 for (i
= 0; i
< src
->cParams
; i
++)
5796 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5802 /* undo the above actions */
5803 for (i
= i
- 1; i
>= 0; i
--)
5804 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5805 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5806 SysFreeString((BSTR
)dest
);
5810 dest
->lprgelemdescParam
= NULL
;
5812 /* special treatment for dispinterfaces: this makes functions appear
5813 * to return their [retval] value when it is really returning an
5815 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5817 if (dest
->cParams
&&
5818 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5820 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5821 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5823 ERR("elemdesc should have started with VT_PTR instead of:\n");
5825 dump_ELEMDESC(elemdesc
);
5826 return E_UNEXPECTED
;
5829 /* copy last parameter to the return value. we are using a flat
5830 * buffer so there is no danger of leaking memory in
5832 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5834 /* remove the last parameter */
5838 /* otherwise this function is made to appear to have no return
5840 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5848 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5850 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5851 if (var_desc
->varkind
== VAR_CONST
)
5852 VariantClear(var_desc
->u
.lpvarValue
);
5853 SysFreeString((BSTR
)var_desc
);
5856 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5858 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5860 if (index
>= This
->typeattr
.cFuncs
)
5861 return TYPE_E_ELEMENTNOTFOUND
;
5863 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5867 /* internal function to make the inherited interfaces' methods appear
5868 * part of the interface */
5869 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5870 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5872 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5874 UINT implemented_funcs
= 0;
5879 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5883 ITypeInfo
*pSubTypeInfo
;
5886 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5890 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5893 &sub_funcs
, hrefoffset
);
5894 implemented_funcs
+= sub_funcs
;
5895 ITypeInfo_Release(pSubTypeInfo
);
5898 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5902 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5906 if (index
< implemented_funcs
)
5907 return E_INVALIDARG
;
5908 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5912 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5914 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5917 switch (pTypeDesc
->vt
)
5919 case VT_USERDEFINED
:
5920 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5924 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5927 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5935 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5938 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5939 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5940 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5943 /* ITypeInfo::GetFuncDesc
5945 * Retrieves the FUNCDESC structure that contains information about a
5946 * specified function.
5949 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5950 LPFUNCDESC
*ppFuncDesc
)
5952 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5953 const FUNCDESC
*internal_funcdesc
;
5955 UINT hrefoffset
= 0;
5957 TRACE("(%p) index %d\n", This
, index
);
5960 return E_INVALIDARG
;
5962 if (This
->needs_layout
)
5963 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5965 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5966 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5967 &internal_funcdesc
, NULL
,
5970 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5971 &internal_funcdesc
);
5974 WARN("description for function %d not found\n", index
);
5978 hr
= TLB_AllocAndInitFuncDesc(
5981 This
->typeattr
.typekind
== TKIND_DISPATCH
);
5983 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
5984 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5986 TRACE("-- 0x%08x\n", hr
);
5990 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5994 SIZE_T size
= sizeof(*src
);
5997 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
5998 if (src
->varkind
== VAR_CONST
)
5999 size
+= sizeof(VARIANT
);
6000 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6002 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6003 if (!dest
) return E_OUTOFMEMORY
;
6006 buffer
= (char *)(dest
+ 1);
6007 if (src
->lpstrSchema
)
6010 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6011 len
= strlenW(src
->lpstrSchema
);
6012 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6013 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6016 if (src
->varkind
== VAR_CONST
)
6020 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6021 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6022 buffer
+= sizeof(VARIANT
);
6023 VariantInit(dest
->u
.lpvarValue
);
6024 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6027 SysFreeString((BSTR
)dest
);
6031 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6034 if (src
->varkind
== VAR_CONST
)
6035 VariantClear(dest
->u
.lpvarValue
);
6036 SysFreeString((BSTR
)dest
);
6043 /* ITypeInfo::GetVarDesc
6045 * Retrieves a VARDESC structure that describes the specified variable.
6048 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6049 LPVARDESC
*ppVarDesc
)
6051 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6052 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6054 TRACE("(%p) index %d\n", This
, index
);
6056 if(index
>= This
->typeattr
.cVars
)
6057 return TYPE_E_ELEMENTNOTFOUND
;
6059 if (This
->needs_layout
)
6060 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6062 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6065 /* ITypeInfo_GetNames
6067 * Retrieves the variable with the specified member ID (or the name of the
6068 * property or method and its parameters) that correspond to the specified
6071 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6072 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6074 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6075 const TLBFuncDesc
*pFDesc
;
6076 const TLBVarDesc
*pVDesc
;
6078 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6081 return E_INVALIDARG
;
6085 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
6088 if(!cMaxNames
|| !pFDesc
->Name
)
6091 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6094 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6095 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6097 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6103 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
6106 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6111 if(This
->impltypes
&&
6112 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
6113 /* recursive search */
6116 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6117 if(SUCCEEDED(result
))
6119 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6120 ITypeInfo_Release(pTInfo
);
6123 WARN("Could not search inherited interface!\n");
6127 WARN("no names found\n");
6130 return TYPE_E_ELEMENTNOTFOUND
;
6136 /* ITypeInfo::GetRefTypeOfImplType
6138 * If a type description describes a COM class, it retrieves the type
6139 * description of the implemented interface types. For an interface,
6140 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6144 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6149 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6152 TRACE("(%p) index %d\n", This
, index
);
6153 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6157 /* only valid on dual interfaces;
6158 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6161 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6167 hr
= TYPE_E_ELEMENTNOTFOUND
;
6170 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6172 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6173 *pRefType
= This
->pTypeLib
->dispatch_href
;
6177 if(index
>= This
->typeattr
.cImplTypes
)
6178 hr
= TYPE_E_ELEMENTNOTFOUND
;
6180 *pRefType
= This
->impltypes
[index
].hRef
;
6181 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6189 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6191 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6197 /* ITypeInfo::GetImplTypeFlags
6199 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6200 * or base interface in a type description.
6202 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6203 UINT index
, INT
*pImplTypeFlags
)
6205 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6207 TRACE("(%p) index %d\n", This
, index
);
6210 return E_INVALIDARG
;
6212 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6213 *pImplTypeFlags
= 0;
6217 if(index
>= This
->typeattr
.cImplTypes
)
6218 return TYPE_E_ELEMENTNOTFOUND
;
6220 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6226 * Maps between member names and member IDs, and parameter names and
6229 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6230 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6232 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6233 const TLBVarDesc
*pVDesc
;
6237 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6240 /* init out parameters in case of failure */
6241 for (i
= 0; i
< cNames
; i
++)
6242 pMemId
[i
] = MEMBERID_NIL
;
6244 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6246 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6247 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6248 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6249 for(i
=1; i
< cNames
; i
++){
6250 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6251 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6253 if( j
<pFDesc
->funcdesc
.cParams
)
6256 ret
=DISP_E_UNKNOWNNAME
;
6258 TRACE("-- 0x%08x\n", ret
);
6262 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, *rgszNames
);
6265 *pMemId
= pVDesc
->vardesc
.memid
;
6268 /* not found, see if it can be found in an inherited interface */
6269 if(This
->impltypes
) {
6270 /* recursive search */
6272 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6274 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6275 ITypeInfo_Release(pTInfo
);
6278 WARN("Could not search inherited interface!\n");
6280 WARN("no names found\n");
6281 return DISP_E_UNKNOWNNAME
;
6287 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6288 __ASM_GLOBAL_FUNC( call_method
,
6290 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6291 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6292 "movl %esp,%ebp\n\t"
6293 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6295 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6297 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6298 "movl 12(%ebp),%edx\n\t"
6299 "movl %esp,%edi\n\t"
6302 "subl %edx,%edi\n\t"
6303 "andl $~15,%edi\n\t"
6304 "movl %edi,%esp\n\t"
6305 "movl 12(%ebp),%ecx\n\t"
6306 "movl 16(%ebp),%esi\n\t"
6309 "1:\tcall *8(%ebp)\n\t"
6310 "subl %esp,%edi\n\t"
6311 "movl 20(%ebp),%ecx\n\t"
6312 "movl %edi,(%ecx)\n\t"
6313 "leal -8(%ebp),%esp\n\t"
6315 __ASM_CFI(".cfi_same_value %edi\n\t")
6317 __ASM_CFI(".cfi_same_value %esi\n\t")
6319 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6320 __ASM_CFI(".cfi_same_value %ebp\n\t")
6323 /* same function but returning floating point */
6324 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6326 /* ITypeInfo::Invoke
6328 * Invokes a method, or accesses a property of an object, that implements the
6329 * interface described by the type description.
6332 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6336 if (TRACE_ON(ole
)) {
6338 TRACE("Calling %p(",func
);
6339 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6340 if (nrargs
> 30) TRACE("...");
6347 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6350 FIXME("unsupported calling convention %d\n",callconv
);
6354 TRACE("returns %08x\n",res
);
6358 #elif defined(__x86_64__)
6360 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6361 __ASM_GLOBAL_FUNC( call_method
,
6363 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6364 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6365 "movq %rsp,%rbp\n\t"
6366 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6368 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6370 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6371 "movq %rcx,%rax\n\t"
6374 "cmovgq %rdx,%rcx\n\t"
6375 "leaq 0(,%rcx,8),%rdx\n\t"
6376 "subq %rdx,%rsp\n\t"
6377 "andq $~15,%rsp\n\t"
6378 "movq %rsp,%rdi\n\t"
6381 "movq 0(%rsp),%rcx\n\t"
6382 "movq 8(%rsp),%rdx\n\t"
6383 "movq 16(%rsp),%r8\n\t"
6384 "movq 24(%rsp),%r9\n\t"
6385 "movq 0(%rsp),%xmm0\n\t"
6386 "movq 8(%rsp),%xmm1\n\t"
6387 "movq 16(%rsp),%xmm2\n\t"
6388 "movq 24(%rsp),%xmm3\n\t"
6390 "leaq -16(%rbp),%rsp\n\t"
6392 __ASM_CFI(".cfi_same_value %rdi\n\t")
6394 __ASM_CFI(".cfi_same_value %rsi\n\t")
6395 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6397 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6398 __ASM_CFI(".cfi_same_value %rbp\n\t")
6401 /* same function but returning floating point */
6402 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)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 __ASM_GLOBAL_FUNC( call_method
,
6410 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6411 * 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)
6414 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6415 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6417 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6418 "beq 1f\n\t" /* Skip allocation if no stack args */
6419 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6420 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6421 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6422 "subs r1, r1, #4\n\t" /* Decrement count */
6423 "bgt 2b\n\t" /* Loop till done */
6427 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6429 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6430 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6432 "blx ip\n\t" /* Call the target function */
6434 "mov sp, fp\n\t" /* Clean the stack using fp */
6435 "pop {fp, pc}\n\t" /* Restore fp and return */
6438 /* same function but returning single/double floating point */
6439 static float (CDECL
* const call_float_method
)(void *, int, const DWORD
*, const DWORD
*) = (void *)call_method
;
6440 static double (CDECL
* const call_double_method
)(void *, int, const DWORD
*, const DWORD
*) = (void *)call_method
;
6442 #endif /* __x86_64__ */
6444 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6447 ITypeInfo
*tinfo2
= NULL
;
6448 TYPEATTR
*tattr
= NULL
;
6450 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6453 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6455 tdesc
->u
.hreftype
, hr
);
6458 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6461 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6462 ITypeInfo_Release(tinfo2
);
6466 switch (tattr
->typekind
)
6473 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6476 case TKIND_INTERFACE
:
6477 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6483 case TKIND_DISPATCH
:
6492 FIXME("TKIND_RECORD unhandled.\n");
6497 FIXME("TKIND_UNION unhandled.\n");
6502 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6506 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6507 ITypeInfo_Release(tinfo2
);
6511 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6515 /* enforce only one level of pointer indirection */
6516 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6518 tdesc
= tdesc
->u
.lptdesc
;
6520 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6521 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6522 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6523 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6524 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6526 VARTYPE vt_userdefined
= 0;
6527 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6528 if (tdesc
->vt
== VT_PTR
)
6530 vt_userdefined
= VT_BYREF
;
6531 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6533 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6535 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6536 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6538 *vt
|= vt_userdefined
;
6550 case VT_USERDEFINED
:
6551 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6558 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6559 hr
= DISP_E_BADVARTYPE
;
6563 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6578 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6584 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6588 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6590 ITypeInfo_Release(tinfo2
);
6594 switch(tattr
->typekind
) {
6596 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6599 case TKIND_INTERFACE
:
6600 case TKIND_DISPATCH
:
6601 *guid
= tattr
->guid
;
6605 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6606 hres
= E_UNEXPECTED
;
6609 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6610 ITypeInfo_Release(tinfo2
);
6614 /***********************************************************************
6615 * DispCallFunc (OLEAUT32.@)
6617 * Invokes a function of the specified calling convention, passing the
6618 * specified arguments and returns the result.
6621 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6622 * oVft [I] The offset in the vtable. See notes.
6623 * cc [I] Calling convention of the function to call.
6624 * vtReturn [I] The return type of the function.
6625 * cActuals [I] Number of parameters.
6626 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6627 * prgpvarg [I] The arguments to pass.
6628 * pvargResult [O] The return value of the function. Can be NULL.
6632 * Failure: HRESULT code.
6635 * The HRESULT return value of this function is not affected by the return
6636 * value of the user supplied function, which is returned in pvargResult.
6638 * If pvInstance is NULL then a non-object function is to be called and oVft
6639 * is the address of the function to call.
6641 * The cc parameter can be one of the following values:
6654 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6655 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6658 int argspos
, stack_offset
;
6663 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6664 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6665 pvargResult
, V_VT(pvargResult
));
6667 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6669 FIXME("unsupported calling convention %d\n",cc
);
6670 return E_INVALIDARG
;
6673 /* maximum size for an argument is sizeof(VARIANT) */
6674 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6676 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6680 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6681 func
= vtable
[oVft
/sizeof(void *)];
6682 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6684 else func
= (void *)oVft
;
6686 for (i
= 0; i
< cActuals
; i
++)
6688 VARIANT
*arg
= prgpvarg
[i
];
6699 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6700 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6704 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6705 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6707 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6708 args
[argspos
++] = V_BOOL(arg
);
6711 args
[argspos
++] = V_UI4(arg
);
6714 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6720 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6723 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6727 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6731 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6732 call_method( func
, argspos
, args
, &stack_offset
);
6737 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6740 WARN("invalid return type %u\n", vtReturn
);
6742 return E_INVALIDARG
;
6744 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6748 if (stack_offset
&& cc
== CC_STDCALL
)
6750 WARN( "stack pointer off by %d\n", stack_offset
);
6751 return DISP_E_BADCALLEE
;
6753 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6754 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6757 #elif defined(__x86_64__)
6763 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6764 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6765 pvargResult
, V_VT(pvargResult
));
6767 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6769 FIXME("unsupported calling convention %d\n",cc
);
6770 return E_INVALIDARG
;
6773 /* maximum size for an argument is sizeof(DWORD_PTR) */
6774 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6776 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6780 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6781 func
= vtable
[oVft
/sizeof(void *)];
6782 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6784 else func
= (void *)oVft
;
6786 for (i
= 0; i
< cActuals
; i
++)
6788 VARIANT
*arg
= prgpvarg
[i
];
6794 args
[argspos
++] = (ULONG_PTR
)arg
;
6796 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6797 args
[argspos
++] = V_BOOL(arg
);
6800 args
[argspos
++] = V_UI8(arg
);
6803 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6809 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6813 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6817 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6818 call_method( func
, argspos
, args
);
6821 WARN("invalid return type %u\n", vtReturn
);
6823 return E_INVALIDARG
;
6825 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6829 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6830 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6833 #elif defined(__arm__)
6847 int rcount
; /* 32-bit register index count */
6849 int scount
= 0; /* single-precision float register index count */
6850 int dcount
= 0; /* double-precision float register index count */
6853 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6854 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6856 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6858 FIXME("unsupported calling convention %d\n",cc
);
6859 return E_INVALIDARG
;
6865 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6866 /* first as it will need to be in the 'r' registers: */
6871 regs
.r
[rcount
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6874 WARN("invalid return type %u\n", vtReturn
);
6875 return E_INVALIDARG
;
6876 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6882 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6883 func
= vtable
[oVft
/sizeof(void *)];
6884 regs
.r
[rcount
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6886 else func
= (void *)oVft
;
6888 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6889 args
= heap_alloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 4 );
6891 for (i
= 0; i
< cActuals
; i
++)
6893 VARIANT
*arg
= prgpvarg
[i
];
6894 DWORD
*pdwarg
= (DWORD
*)(arg
); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6895 int ntemp
; /* Used for counting words split between registers and stack */
6901 case VT_R8
: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6904 dcount
= max( (scount
+ 1) / 2, dcount
);
6907 regs
.sd
.d
[dcount
++] = V_R8(arg
);
6911 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6912 memcpy( &args
[argspos
], &V_R8(arg
), sizeof(V_R8(arg
)) );
6913 argspos
+= sizeof(V_R8(arg
)) / sizeof(DWORD
);
6917 case VT_I8
: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6922 rcount
+= (rcount
% 2); /* align rcount to 8-byte register pair */
6923 memcpy( ®s
.r
[rcount
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6924 rcount
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6928 rcount
= 4; /* Make sure we flag that all 'r' regs are full */
6929 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6930 memcpy( &args
[argspos
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6931 argspos
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6934 case VT_DECIMAL
: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6936 /* 8-byte align 'r' and/or stack: */
6938 rcount
+= (rcount
% 2);
6942 argspos
+= (argspos
% 2);
6944 ntemp
= sizeof(*arg
) / sizeof(DWORD
);
6948 regs
.r
[rcount
++] = *pdwarg
++;
6950 args
[argspos
++] = *pdwarg
++;
6954 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6956 regs
.r
[rcount
++] = V_BOOL(arg
);
6958 args
[argspos
++] = V_BOOL(arg
);
6960 case VT_R4
: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6962 if (!(scount
% 2)) scount
= max( scount
, dcount
* 2 );
6964 regs
.sd
.s
[scount
++] = V_R4(arg
);
6966 args
[argspos
++] = V_UI4(arg
);
6971 regs
.r
[rcount
++] = V_UI4(arg
);
6973 args
[argspos
++] = V_UI4(arg
);
6976 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6979 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 8-byte */
6983 case VT_EMPTY
: /* EMPTY = no return value */
6984 case VT_DECIMAL
: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6986 call_method( func
, argspos
, args
, (DWORD
*)®s
);
6989 V_R4(pvargResult
) = call_float_method( func
, argspos
, args
, (DWORD
*)®s
);
6993 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, (DWORD
*)®s
);
6998 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
7001 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
7005 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
7006 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
7010 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7011 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
7016 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
7018 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
7021 #define INVBUF_ELEMENT_SIZE \
7022 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7023 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7024 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7025 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7026 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7027 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7028 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7029 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7031 static HRESULT WINAPI
ITypeInfo_fnInvoke(
7036 DISPPARAMS
*pDispParams
,
7037 VARIANT
*pVarResult
,
7038 EXCEPINFO
*pExcepInfo
,
7041 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7043 unsigned int var_index
;
7046 const TLBFuncDesc
*pFuncInfo
;
7049 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7050 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
7053 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7054 return DISP_E_MEMBERNOTFOUND
;
7058 ERR("NULL pDispParams not allowed\n");
7059 return E_INVALIDARG
;
7062 dump_DispParms(pDispParams
);
7064 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7066 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7067 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7068 return E_INVALIDARG
;
7071 /* we do this instead of using GetFuncDesc since it will return a fake
7072 * FUNCDESC for dispinterfaces and we want the real function description */
7073 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7074 pFuncInfo
= &This
->funcdescs
[fdc
];
7075 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7076 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7077 !func_restricted( &pFuncInfo
->funcdesc
))
7081 if (fdc
< This
->typeattr
.cFuncs
) {
7082 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7086 TRACE("invoking:\n");
7087 dump_TLBFuncDescOne(pFuncInfo
);
7090 switch (func_desc
->funckind
) {
7091 case FUNC_PUREVIRTUAL
:
7092 case FUNC_VIRTUAL
: {
7093 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7095 VARIANT retval
; /* pointer for storing byref retvals in */
7096 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7097 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7098 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7099 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7100 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7101 UINT vargs_converted
=0;
7105 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7107 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7109 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7110 hres
= DISP_E_PARAMNOTFOUND
;
7115 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7117 ERR("functions with the vararg attribute do not support named arguments\n");
7118 hres
= DISP_E_NONAMEDARGS
;
7122 for (i
= 0; i
< func_desc
->cParams
; i
++)
7124 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7125 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7130 TRACE("changing args\n");
7131 for (i
= 0; i
< func_desc
->cParams
; i
++)
7133 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7134 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7135 VARIANTARG
*src_arg
;
7137 if (wParamFlags
& PARAMFLAG_FLCID
)
7140 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7142 V_I4(arg
) = This
->pTypeLib
->lcid
;
7151 for (j
= 0; j
< cNamedArgs
; j
++)
7152 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7154 src_arg
= &pDispParams
->rgvarg
[j
];
7159 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7161 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7165 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7167 /* under most conditions the caller is not allowed to
7168 * pass in a dispparam arg in the index of what would be
7169 * the retval parameter. however, there is an exception
7170 * where the extra parameter is used in an extra
7171 * IDispatch::Invoke below */
7172 if ((i
< pDispParams
->cArgs
) &&
7173 ((func_desc
->cParams
!= 1) || !pVarResult
||
7174 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7176 hres
= DISP_E_BADPARAMCOUNT
;
7180 /* note: this check is placed so that if the caller passes
7181 * in a VARIANTARG for the retval we just ignore it, like
7183 if (i
== func_desc
->cParams
- 1)
7186 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7187 memset(arg
, 0, sizeof(*arg
));
7188 V_VT(arg
) = rgvt
[i
];
7189 memset(&retval
, 0, sizeof(retval
));
7190 V_BYREF(arg
) = &retval
;
7194 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7195 hres
= E_UNEXPECTED
;
7201 TRACE("%s\n", debugstr_variant(src_arg
));
7203 if(rgvt
[i
]!=V_VT(src_arg
))
7205 if (rgvt
[i
] == VT_VARIANT
)
7206 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7207 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7209 if (rgvt
[i
] == V_VT(src_arg
))
7210 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7213 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7214 if (wParamFlags
& PARAMFLAG_FIN
)
7215 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7216 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7218 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7220 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7223 SAFEARRAYBOUND bound
;
7227 bound
.cElements
= pDispParams
->cArgs
-i
;
7228 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7230 ERR("SafeArrayCreate failed\n");
7233 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7236 ERR("SafeArrayAccessData failed with %x\n", hres
);
7237 SafeArrayDestroy(a
);
7240 for (j
= 0; j
< bound
.cElements
; j
++)
7241 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7242 hres
= SafeArrayUnaccessData(a
);
7245 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7246 SafeArrayDestroy(a
);
7249 if (rgvt
[i
] & VT_BYREF
)
7250 V_BYREF(&rgvarg
[i
]) = &a
;
7252 V_ARRAY(&rgvarg
[i
]) = a
;
7253 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7255 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7257 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7258 if (wParamFlags
& PARAMFLAG_FIN
)
7259 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7261 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7262 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7263 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7265 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7267 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7268 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7272 /* FIXME: this doesn't work for VT_BYREF arguments if
7273 * they are not the same type as in the paramdesc */
7274 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7275 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7276 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7281 ERR("failed to convert param %d to %s from %s\n", i
,
7282 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7285 prgpvarg
[i
] = &rgvarg
[i
];
7289 prgpvarg
[i
] = src_arg
;
7292 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7293 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7294 && V_UNKNOWN(prgpvarg
[i
])) {
7295 IUnknown
*userdefined_iface
;
7298 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7302 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7304 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7308 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7309 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7312 else if (wParamFlags
& PARAMFLAG_FOPT
)
7315 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7316 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7318 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7324 VARIANTARG
*missing_arg
;
7325 /* if the function wants a pointer to a variant then
7326 * set that up, otherwise just pass the VT_ERROR in
7327 * the argument by value */
7328 if (rgvt
[i
] & VT_BYREF
)
7330 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7331 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7332 V_VARIANTREF(arg
) = missing_arg
;
7336 V_VT(missing_arg
) = VT_ERROR
;
7337 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7342 hres
= DISP_E_BADPARAMCOUNT
;
7346 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7348 /* VT_VOID is a special case for return types, so it is not
7349 * handled in the general function */
7350 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7351 V_VT(&varresult
) = VT_EMPTY
;
7354 V_VT(&varresult
) = 0;
7355 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7356 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7359 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7360 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7361 prgpvarg
, &varresult
);
7363 vargs_converted
= 0;
7365 for (i
= 0; i
< func_desc
->cParams
; i
++)
7367 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7368 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7370 if (wParamFlags
& PARAMFLAG_FLCID
)
7372 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7374 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7378 VariantInit(pVarResult
);
7379 /* deref return value */
7380 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7383 VARIANT_ClearInd(prgpvarg
[i
]);
7385 else if (vargs_converted
< pDispParams
->cArgs
)
7387 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7388 if (wParamFlags
& PARAMFLAG_FOUT
)
7390 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7392 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7396 ERR("failed to convert param %d to vt %d\n", i
,
7397 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7402 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7403 func_desc
->cParamsOpt
< 0 &&
7404 i
== func_desc
->cParams
-1)
7406 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7409 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7412 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7415 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7418 ERR("SafeArrayAccessData failed with %x\n", hres
);
7421 for (j
= 0; j
<= ubound
; j
++)
7422 VariantClear(&v
[j
]);
7423 hres
= SafeArrayUnaccessData(a
);
7426 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7430 VariantClear(&rgvarg
[i
]);
7433 else if (wParamFlags
& PARAMFLAG_FOPT
)
7435 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7436 VariantClear(&rgvarg
[i
]);
7439 VariantClear(&missing_arg
[i
]);
7442 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7444 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7445 hres
= DISP_E_EXCEPTION
;
7448 IErrorInfo
*pErrorInfo
;
7449 pExcepInfo
->scode
= V_ERROR(&varresult
);
7450 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7452 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7453 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7454 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7455 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7457 IErrorInfo_Release(pErrorInfo
);
7461 if (V_VT(&varresult
) != VT_ERROR
)
7463 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7467 VariantClear(pVarResult
);
7468 *pVarResult
= varresult
;
7471 VariantClear(&varresult
);
7474 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7475 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7476 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7477 (pDispParams
->cArgs
!= 0))
7479 if (V_VT(pVarResult
) == VT_DISPATCH
)
7481 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7482 /* Note: not VariantClear; we still need the dispatch
7483 * pointer to be valid */
7484 VariantInit(pVarResult
);
7485 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7486 GetSystemDefaultLCID(), wFlags
,
7487 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7488 IDispatch_Release(pDispatch
);
7492 VariantClear(pVarResult
);
7493 hres
= DISP_E_NOTACOLLECTION
;
7501 case FUNC_DISPATCH
: {
7504 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7505 if (SUCCEEDED(hres
)) {
7506 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7507 hres
= IDispatch_Invoke(
7508 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7509 pVarResult
,pExcepInfo
,pArgErr
7512 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7513 IDispatch_Release(disp
);
7515 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7519 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7524 TRACE("-- 0x%08x\n", hres
);
7527 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7530 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7531 if(FAILED(hres
)) return hres
;
7533 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7534 dump_VARDESC(var_desc
);
7535 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7539 /* not found, look for it in inherited interfaces */
7540 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7541 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7542 if(This
->impltypes
) {
7543 /* recursive search */
7545 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7546 if(SUCCEEDED(hres
)){
7547 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7548 ITypeInfo_Release(pTInfo
);
7551 WARN("Could not search inherited interface!\n");
7554 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7555 return DISP_E_MEMBERNOTFOUND
;
7558 /* ITypeInfo::GetDocumentation
7560 * Retrieves the documentation string, the complete Help file name and path,
7561 * and the context ID for the Help topic for a specified type description.
7563 * (Can be tested by the Visual Basic Editor in Word for instance.)
7565 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7566 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7567 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7569 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7570 const TLBFuncDesc
*pFDesc
;
7571 const TLBVarDesc
*pVDesc
;
7572 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7573 " HelpContext(%p) HelpFile(%p)\n",
7574 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7575 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7577 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7579 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7581 *pdwHelpContext
=This
->dwHelpContext
;
7583 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7585 }else {/* for a member */
7586 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7589 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7591 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7593 *pdwHelpContext
=pFDesc
->helpcontext
;
7595 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7598 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
7601 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7603 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7605 *pdwHelpContext
=pVDesc
->HelpContext
;
7607 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7612 if(This
->impltypes
&&
7613 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7614 /* recursive search */
7617 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7618 if(SUCCEEDED(result
)) {
7619 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7620 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7621 ITypeInfo_Release(pTInfo
);
7624 WARN("Could not search inherited interface!\n");
7627 WARN("member %d not found\n", memid
);
7628 return TYPE_E_ELEMENTNOTFOUND
;
7631 /* ITypeInfo::GetDllEntry
7633 * Retrieves a description or specification of an entry point for a function
7636 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7637 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7640 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7641 const TLBFuncDesc
*pFDesc
;
7643 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7645 if (pBstrDllName
) *pBstrDllName
= NULL
;
7646 if (pBstrName
) *pBstrName
= NULL
;
7647 if (pwOrdinal
) *pwOrdinal
= 0;
7649 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7650 return TYPE_E_BADMODULEKIND
;
7652 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7654 dump_TypeInfo(This
);
7656 dump_TLBFuncDescOne(pFDesc
);
7659 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7661 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7663 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7671 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7674 return TYPE_E_ELEMENTNOTFOUND
;
7677 /* internal function to make the inherited interfaces' methods appear
7678 * part of the interface */
7679 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7680 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7682 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7685 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7687 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7689 ITypeInfo
*pSubTypeInfo
;
7691 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7695 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7697 ITypeInfo_Release(pSubTypeInfo
);
7701 *hRefType
-= DISPATCH_HREF_OFFSET
;
7703 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7704 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7709 struct search_res_tlb_params
7715 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7717 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7718 static const WCHAR formatW
[] = {'\\','%','d',0};
7719 WCHAR szPath
[MAX_PATH
+1];
7720 ITypeLib
*pTLib
= NULL
;
7724 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7727 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7730 if (snprintfW(szPath
+ len
, sizeof(szPath
)/sizeof(WCHAR
) - len
, formatW
, LOWORD(lpszName
)) < 0)
7733 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7736 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7737 if (IsEqualGUID(params
->guid
, impl
->guid
))
7739 params
->pTLib
= pTLib
;
7740 return FALSE
; /* stop enumeration */
7742 ITypeLib_Release(pTLib
);
7748 /* ITypeInfo::GetRefTypeInfo
7750 * If a type description references other type descriptions, it retrieves
7751 * the referenced type descriptions.
7753 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7756 ITypeInfo
**ppTInfo
)
7758 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7759 HRESULT result
= E_FAIL
;
7762 return E_INVALIDARG
;
7764 if ((INT
)hRefType
< 0) {
7765 ITypeInfoImpl
*pTypeInfoImpl
;
7767 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7768 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7769 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7770 return TYPE_E_ELEMENTNOTFOUND
;
7772 /* when we meet a DUAL typeinfo, we must create the alternate
7775 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7777 *pTypeInfoImpl
= *This
;
7778 pTypeInfoImpl
->ref
= 0;
7779 list_init(&pTypeInfoImpl
->custdata_list
);
7781 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7782 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7784 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7786 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7787 /* the AddRef implicitly adds a reference to the parent typelib, which
7788 * stops the copied data from being destroyed until the new typeinfo's
7789 * refcount goes to zero, but we need to signal to the new instance to
7790 * not free its data structures when it is destroyed */
7791 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7793 ITypeInfo_AddRef(*ppTInfo
);
7796 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7797 (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7799 HREFTYPE href_dispatch
= hRefType
;
7800 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7802 TLBRefType
*ref_type
;
7803 ITypeLib
*pTLib
= NULL
;
7806 if(!(hRefType
& 0x1)){
7807 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7809 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7812 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7813 ITypeInfo_AddRef(*ppTInfo
);
7819 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7821 if(ref_type
->reference
== (hRefType
& (~0x3)))
7824 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7826 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7830 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7832 TRACE("internal reference\n");
7833 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7835 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7836 TRACE("typeinfo in imported typelib that is already loaded\n");
7837 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7838 ITypeLib_AddRef(pTLib
);
7841 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
7842 struct search_res_tlb_params params
;
7845 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7847 /* Search in resource table */
7848 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
7849 params
.pTLib
= NULL
;
7850 EnumResourceNamesW(NULL
, TYPELIBW
, search_res_tlb
, (LONG_PTR
)¶ms
);
7851 pTLib
= params
.pTLib
;
7856 /* Search on disk */
7857 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7858 ref_type
->pImpTLInfo
->wVersionMajor
,
7859 ref_type
->pImpTLInfo
->wVersionMinor
,
7860 This
->pTypeLib
->syskind
,
7861 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7863 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7865 result
= LoadTypeLib(libnam
, &pTLib
);
7866 SysFreeString(libnam
);
7869 if(SUCCEEDED(result
)) {
7870 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7871 ITypeLib_AddRef(pTLib
);
7875 if(SUCCEEDED(result
)) {
7876 if(ref_type
->index
== TLB_REF_USE_GUID
)
7877 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7879 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7882 ITypeLib_Release(pTLib
);
7886 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7887 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7891 /* ITypeInfo::AddressOfMember
7893 * Retrieves the addresses of static functions or variables, such as those
7896 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7897 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7899 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7905 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7907 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7911 module
= LoadLibraryW(dll
);
7914 ERR("couldn't load %s\n", debugstr_w(dll
));
7916 SysFreeString(entry
);
7917 return STG_E_FILENOTFOUND
;
7919 /* FIXME: store library somewhere where we can free it */
7924 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7925 entryA
= heap_alloc(len
);
7926 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7928 *ppv
= GetProcAddress(module
, entryA
);
7930 ERR("function not found %s\n", debugstr_a(entryA
));
7936 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7938 ERR("function not found %d\n", ordinal
);
7942 SysFreeString(entry
);
7945 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7950 /* ITypeInfo::CreateInstance
7952 * Creates a new instance of a type that describes a component object class
7955 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7956 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7958 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7962 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7968 WARN("Not able to aggregate\n");
7969 return CLASS_E_NOAGGREGATION
;
7972 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7973 if(FAILED(hr
)) return hr
;
7975 if(pTA
->typekind
!= TKIND_COCLASS
)
7977 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7983 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7986 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7987 TRACE("GetActiveObject rets %08x\n", hr
);
7990 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7991 IUnknown_Release(pUnk
);
7996 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7997 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8001 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8005 /* ITypeInfo::GetMops
8007 * Retrieves marshalling information.
8009 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
8012 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8013 FIXME("(%p %d) stub!\n", This
, memid
);
8018 /* ITypeInfo::GetContainingTypeLib
8020 * Retrieves the containing type library and the index of the type description
8021 * within that type library.
8023 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8024 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8026 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8028 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8030 *pIndex
=This
->index
;
8031 TRACE("returning pIndex=%d\n", *pIndex
);
8035 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8036 ITypeLib_AddRef(*ppTLib
);
8037 TRACE("returning ppTLib=%p\n", *ppTLib
);
8043 /* ITypeInfo::ReleaseTypeAttr
8045 * Releases a TYPEATTR previously returned by Get
8048 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8049 TYPEATTR
* pTypeAttr
)
8051 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8052 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8053 heap_free(pTypeAttr
);
8056 /* ITypeInfo::ReleaseFuncDesc
8058 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8060 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8062 FUNCDESC
*pFuncDesc
)
8064 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8067 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8069 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8070 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8071 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8073 SysFreeString((BSTR
)pFuncDesc
);
8076 /* ITypeInfo::ReleaseVarDesc
8078 * Releases a VARDESC previously returned by GetVarDesc.
8080 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8083 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8084 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8086 TLB_FreeVarDesc(pVarDesc
);
8089 /* ITypeInfo2::GetTypeKind
8091 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8094 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8095 TYPEKIND
*pTypeKind
)
8097 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8098 *pTypeKind
= This
->typeattr
.typekind
;
8099 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8103 /* ITypeInfo2::GetTypeFlags
8105 * Returns the type flags without any allocations. This returns a DWORD type
8106 * flag, which expands the type flags without growing the TYPEATTR (type
8110 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8112 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8113 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8114 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
8118 /* ITypeInfo2::GetFuncIndexOfMemId
8119 * Binds to a specific member based on a known DISPID, where the member name
8120 * is not known (for example, when binding to a default member).
8123 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8124 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8126 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8130 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8131 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8132 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8135 if(fdc
< This
->typeattr
.cFuncs
) {
8139 result
= TYPE_E_ELEMENTNOTFOUND
;
8141 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
8142 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8146 /* TypeInfo2::GetVarIndexOfMemId
8148 * Binds to a specific member based on a known DISPID, where the member name
8149 * is not known (for example, when binding to a default member).
8152 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8153 MEMBERID memid
, UINT
*pVarIndex
)
8155 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8156 TLBVarDesc
*pVarInfo
;
8158 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8160 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
8162 return TYPE_E_ELEMENTNOTFOUND
;
8164 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8169 /* ITypeInfo2::GetCustData
8171 * Gets the custom data
8173 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8178 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8179 TLBCustData
*pCData
;
8181 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8183 if(!guid
|| !pVarVal
)
8184 return E_INVALIDARG
;
8186 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8188 VariantInit( pVarVal
);
8190 VariantCopy( pVarVal
, &pCData
->data
);
8192 VariantClear( pVarVal
);
8196 /* ITypeInfo2::GetFuncCustData
8198 * Gets the custom data
8200 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8206 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8207 TLBCustData
*pCData
;
8208 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8210 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8212 if(index
>= This
->typeattr
.cFuncs
)
8213 return TYPE_E_ELEMENTNOTFOUND
;
8215 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8217 return TYPE_E_ELEMENTNOTFOUND
;
8219 VariantInit(pVarVal
);
8220 VariantCopy(pVarVal
, &pCData
->data
);
8225 /* ITypeInfo2::GetParamCustData
8227 * Gets the custom data
8229 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8236 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8237 TLBCustData
*pCData
;
8238 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8240 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8241 debugstr_guid(guid
), pVarVal
);
8243 if(indexFunc
>= This
->typeattr
.cFuncs
)
8244 return TYPE_E_ELEMENTNOTFOUND
;
8246 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8247 return TYPE_E_ELEMENTNOTFOUND
;
8249 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8251 return TYPE_E_ELEMENTNOTFOUND
;
8253 VariantInit(pVarVal
);
8254 VariantCopy(pVarVal
, &pCData
->data
);
8259 /* ITypeInfo2::GetVarCustData
8261 * Gets the custom data
8263 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8269 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8270 TLBCustData
*pCData
;
8271 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8273 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8275 if(index
>= This
->typeattr
.cVars
)
8276 return TYPE_E_ELEMENTNOTFOUND
;
8278 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8280 return TYPE_E_ELEMENTNOTFOUND
;
8282 VariantInit(pVarVal
);
8283 VariantCopy(pVarVal
, &pCData
->data
);
8288 /* ITypeInfo2::GetImplCustData
8290 * Gets the custom data
8292 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8298 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8299 TLBCustData
*pCData
;
8300 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8302 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8304 if(index
>= This
->typeattr
.cImplTypes
)
8305 return TYPE_E_ELEMENTNOTFOUND
;
8307 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8309 return TYPE_E_ELEMENTNOTFOUND
;
8311 VariantInit(pVarVal
);
8312 VariantCopy(pVarVal
, &pCData
->data
);
8317 /* ITypeInfo2::GetDocumentation2
8319 * Retrieves the documentation string, the complete Help file name and path,
8320 * the localization context to use, and the context ID for the library Help
8321 * topic in the Help file.
8324 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8328 BSTR
*pbstrHelpString
,
8329 DWORD
*pdwHelpStringContext
,
8330 BSTR
*pbstrHelpStringDll
)
8332 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8333 const TLBFuncDesc
*pFDesc
;
8334 const TLBVarDesc
*pVDesc
;
8335 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8336 "HelpStringContext(%p) HelpStringDll(%p)\n",
8337 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8338 pbstrHelpStringDll
);
8339 /* the help string should be obtained from the helpstringdll,
8340 * using the _DLLGetDocumentation function, based on the supplied
8341 * lcid. Nice to do sometime...
8343 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8345 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8346 if(pdwHelpStringContext
)
8347 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8348 if(pbstrHelpStringDll
)
8349 *pbstrHelpStringDll
=
8350 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8352 }else {/* for a member */
8353 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
8356 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8357 if(pdwHelpStringContext
)
8358 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8359 if(pbstrHelpStringDll
)
8360 *pbstrHelpStringDll
=
8361 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8364 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
8367 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8368 if(pdwHelpStringContext
)
8369 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8370 if(pbstrHelpStringDll
)
8371 *pbstrHelpStringDll
=
8372 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8376 return TYPE_E_ELEMENTNOTFOUND
;
8379 /* ITypeInfo2::GetAllCustData
8381 * Gets all custom data items for the Type info.
8384 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8386 CUSTDATA
*pCustData
)
8388 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8390 TRACE("%p %p\n", This
, pCustData
);
8392 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8395 /* ITypeInfo2::GetAllFuncCustData
8397 * Gets all custom data items for the specified Function
8400 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8403 CUSTDATA
*pCustData
)
8405 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8406 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8408 TRACE("%p %u %p\n", This
, index
, pCustData
);
8410 if(index
>= This
->typeattr
.cFuncs
)
8411 return TYPE_E_ELEMENTNOTFOUND
;
8413 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8416 /* ITypeInfo2::GetAllParamCustData
8418 * Gets all custom data items for the Functions
8421 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8422 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8424 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8425 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8427 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8429 if(indexFunc
>= This
->typeattr
.cFuncs
)
8430 return TYPE_E_ELEMENTNOTFOUND
;
8432 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8433 return TYPE_E_ELEMENTNOTFOUND
;
8435 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8438 /* ITypeInfo2::GetAllVarCustData
8440 * Gets all custom data items for the specified Variable
8443 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8444 UINT index
, CUSTDATA
*pCustData
)
8446 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8447 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8449 TRACE("%p %u %p\n", This
, index
, pCustData
);
8451 if(index
>= This
->typeattr
.cVars
)
8452 return TYPE_E_ELEMENTNOTFOUND
;
8454 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8457 /* ITypeInfo2::GetAllImplCustData
8459 * Gets all custom data items for the specified implementation type
8462 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8465 CUSTDATA
*pCustData
)
8467 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8468 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8470 TRACE("%p %u %p\n", This
, index
, pCustData
);
8472 if(index
>= This
->typeattr
.cImplTypes
)
8473 return TYPE_E_ELEMENTNOTFOUND
;
8475 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8478 static const ITypeInfo2Vtbl tinfvt
=
8481 ITypeInfo_fnQueryInterface
,
8483 ITypeInfo_fnRelease
,
8485 ITypeInfo_fnGetTypeAttr
,
8486 ITypeInfo_fnGetTypeComp
,
8487 ITypeInfo_fnGetFuncDesc
,
8488 ITypeInfo_fnGetVarDesc
,
8489 ITypeInfo_fnGetNames
,
8490 ITypeInfo_fnGetRefTypeOfImplType
,
8491 ITypeInfo_fnGetImplTypeFlags
,
8492 ITypeInfo_fnGetIDsOfNames
,
8494 ITypeInfo_fnGetDocumentation
,
8495 ITypeInfo_fnGetDllEntry
,
8496 ITypeInfo_fnGetRefTypeInfo
,
8497 ITypeInfo_fnAddressOfMember
,
8498 ITypeInfo_fnCreateInstance
,
8499 ITypeInfo_fnGetMops
,
8500 ITypeInfo_fnGetContainingTypeLib
,
8501 ITypeInfo_fnReleaseTypeAttr
,
8502 ITypeInfo_fnReleaseFuncDesc
,
8503 ITypeInfo_fnReleaseVarDesc
,
8505 ITypeInfo2_fnGetTypeKind
,
8506 ITypeInfo2_fnGetTypeFlags
,
8507 ITypeInfo2_fnGetFuncIndexOfMemId
,
8508 ITypeInfo2_fnGetVarIndexOfMemId
,
8509 ITypeInfo2_fnGetCustData
,
8510 ITypeInfo2_fnGetFuncCustData
,
8511 ITypeInfo2_fnGetParamCustData
,
8512 ITypeInfo2_fnGetVarCustData
,
8513 ITypeInfo2_fnGetImplTypeCustData
,
8514 ITypeInfo2_fnGetDocumentation2
,
8515 ITypeInfo2_fnGetAllCustData
,
8516 ITypeInfo2_fnGetAllFuncCustData
,
8517 ITypeInfo2_fnGetAllParamCustData
,
8518 ITypeInfo2_fnGetAllVarCustData
,
8519 ITypeInfo2_fnGetAllImplTypeCustData
,
8522 /******************************************************************************
8523 * CreateDispTypeInfo [OLEAUT32.31]
8525 * Build type information for an object so it can be called through an
8526 * IDispatch interface.
8529 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8530 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8533 * This call allows an objects methods to be accessed through IDispatch, by
8534 * building an ITypeInfo object that IDispatch can use to call through.
8536 HRESULT WINAPI
CreateDispTypeInfo(
8537 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8538 LCID lcid
, /* [I] Locale Id */
8539 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8541 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8542 ITypeLibImpl
*pTypeLibImpl
;
8543 unsigned int param
, func
;
8544 TLBFuncDesc
*pFuncDesc
;
8548 pTypeLibImpl
= TypeLibImpl_Constructor();
8549 if (!pTypeLibImpl
) return E_FAIL
;
8551 pTypeLibImpl
->TypeInfoCount
= 2;
8552 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8554 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8555 pTIIface
->pTypeLib
= pTypeLibImpl
;
8556 pTIIface
->index
= 0;
8557 pTIIface
->Name
= NULL
;
8558 pTIIface
->dwHelpContext
= -1;
8559 pTIIface
->guid
= NULL
;
8560 pTIIface
->typeattr
.lcid
= lcid
;
8561 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8562 pTIIface
->typeattr
.wMajorVerNum
= 0;
8563 pTIIface
->typeattr
.wMinorVerNum
= 0;
8564 pTIIface
->typeattr
.cbAlignment
= 2;
8565 pTIIface
->typeattr
.cbSizeInstance
= -1;
8566 pTIIface
->typeattr
.cbSizeVft
= -1;
8567 pTIIface
->typeattr
.cFuncs
= 0;
8568 pTIIface
->typeattr
.cImplTypes
= 0;
8569 pTIIface
->typeattr
.cVars
= 0;
8570 pTIIface
->typeattr
.wTypeFlags
= 0;
8571 pTIIface
->hreftype
= 0;
8573 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8574 pFuncDesc
= pTIIface
->funcdescs
;
8575 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8576 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8577 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8578 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8579 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8580 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8581 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8582 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8583 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8584 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8585 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8586 pFuncDesc
->funcdesc
.cScodes
= 0;
8587 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8588 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8589 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8590 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8591 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8592 md
->cArgs
* sizeof(ELEMDESC
));
8593 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8594 for(param
= 0; param
< md
->cArgs
; param
++) {
8595 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8596 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8598 pFuncDesc
->helpcontext
= 0;
8599 pFuncDesc
->HelpStringContext
= 0;
8600 pFuncDesc
->HelpString
= NULL
;
8601 pFuncDesc
->Entry
= NULL
;
8602 list_init(&pFuncDesc
->custdata_list
);
8603 pTIIface
->typeattr
.cFuncs
++;
8607 dump_TypeInfo(pTIIface
);
8609 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8610 pTIClass
->pTypeLib
= pTypeLibImpl
;
8611 pTIClass
->index
= 1;
8612 pTIClass
->Name
= NULL
;
8613 pTIClass
->dwHelpContext
= -1;
8614 pTIClass
->guid
= NULL
;
8615 pTIClass
->typeattr
.lcid
= lcid
;
8616 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8617 pTIClass
->typeattr
.wMajorVerNum
= 0;
8618 pTIClass
->typeattr
.wMinorVerNum
= 0;
8619 pTIClass
->typeattr
.cbAlignment
= 2;
8620 pTIClass
->typeattr
.cbSizeInstance
= -1;
8621 pTIClass
->typeattr
.cbSizeVft
= -1;
8622 pTIClass
->typeattr
.cFuncs
= 0;
8623 pTIClass
->typeattr
.cImplTypes
= 1;
8624 pTIClass
->typeattr
.cVars
= 0;
8625 pTIClass
->typeattr
.wTypeFlags
= 0;
8626 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8628 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8630 ref
= heap_alloc_zero(sizeof(*ref
));
8631 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8632 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8634 dump_TypeInfo(pTIClass
);
8636 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8638 ITypeInfo_AddRef(*pptinfo
);
8639 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8645 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8647 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8649 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8652 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8654 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8656 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8659 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8661 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8663 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8666 static HRESULT WINAPI
ITypeComp_fnBind(
8671 ITypeInfo
** ppTInfo
,
8672 DESCKIND
* pDescKind
,
8675 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8676 const TLBFuncDesc
*pFDesc
;
8677 const TLBVarDesc
*pVDesc
;
8678 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8681 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8683 *pDescKind
= DESCKIND_NONE
;
8684 pBindPtr
->lpfuncdesc
= NULL
;
8687 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8688 pFDesc
= &This
->funcdescs
[fdc
];
8689 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8690 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8693 /* name found, but wrong flags */
8694 hr
= TYPE_E_TYPEMISMATCH
;
8698 if (fdc
< This
->typeattr
.cFuncs
)
8700 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8702 &pBindPtr
->lpfuncdesc
,
8703 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8706 *pDescKind
= DESCKIND_FUNCDESC
;
8707 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8708 ITypeInfo_AddRef(*ppTInfo
);
8711 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, szName
);
8713 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8716 *pDescKind
= DESCKIND_VARDESC
;
8717 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8718 ITypeInfo_AddRef(*ppTInfo
);
8723 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8724 /* recursive search */
8728 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8731 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8732 ITypeInfo_Release(pTInfo
);
8736 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8737 ITypeComp_Release(pTComp
);
8738 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8739 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8741 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8742 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8743 SysFreeString((BSTR
)tmp
);
8747 WARN("Could not search inherited interface!\n");
8749 if (hr
== DISP_E_MEMBERNOTFOUND
)
8751 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8755 static HRESULT WINAPI
ITypeComp_fnBindType(
8759 ITypeInfo
** ppTInfo
,
8760 ITypeComp
** ppTComp
)
8762 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8764 /* strange behaviour (does nothing) but like the
8767 if (!ppTInfo
|| !ppTComp
)
8776 static const ITypeCompVtbl tcompvt
=
8779 ITypeComp_fnQueryInterface
,
8781 ITypeComp_fnRelease
,
8784 ITypeComp_fnBindType
8787 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8788 ICreateTypeLib2
** ppctlib
)
8793 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8795 if (!szFile
) return E_INVALIDARG
;
8797 This
= TypeLibImpl_Constructor();
8799 return E_OUTOFMEMORY
;
8801 This
->lcid
= GetSystemDefaultLCID();
8802 This
->syskind
= syskind
;
8803 This
->ptr_size
= get_ptr_size(syskind
);
8805 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8807 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8808 return E_OUTOFMEMORY
;
8810 lstrcpyW(This
->path
, szFile
);
8812 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8813 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8817 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8818 REFIID riid
, void **object
)
8820 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8822 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8825 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8827 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8829 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8832 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8834 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8836 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8839 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8840 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8842 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8843 ITypeInfoImpl
*info
;
8846 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8848 if (!ctinfo
|| !name
)
8849 return E_INVALIDARG
;
8851 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8853 return TYPE_E_NAMECONFLICT
;
8855 if (This
->typeinfos
)
8856 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8857 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8859 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8861 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8863 info
->pTypeLib
= This
;
8864 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8865 info
->index
= This
->TypeInfoCount
;
8866 info
->typeattr
.typekind
= kind
;
8867 info
->typeattr
.cbAlignment
= 4;
8869 switch (info
->typeattr
.typekind
) {
8871 case TKIND_INTERFACE
:
8872 case TKIND_DISPATCH
:
8874 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
8878 info
->typeattr
.cbSizeInstance
= 0;
8881 info
->typeattr
.cbSizeInstance
= 2;
8884 info
->typeattr
.cbSizeInstance
= -0x75;
8887 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
8888 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
8892 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8893 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8895 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8899 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8901 ++This
->TypeInfoCount
;
8906 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8909 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8911 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8914 return E_INVALIDARG
;
8916 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8921 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8922 WORD majorVerNum
, WORD minorVerNum
)
8924 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8926 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8928 This
->ver_major
= majorVerNum
;
8929 This
->ver_minor
= minorVerNum
;
8934 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8937 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8939 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8941 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8946 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8949 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8951 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8954 return E_INVALIDARG
;
8956 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8961 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8962 LPOLESTR helpFileName
)
8964 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8966 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8969 return E_INVALIDARG
;
8971 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8976 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8979 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8981 TRACE("%p %d\n", This
, helpContext
);
8983 This
->dwHelpContext
= helpContext
;
8988 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8991 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8993 TRACE("%p %x\n", This
, lcid
);
8995 This
->set_lcid
= lcid
;
9000 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9003 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9005 TRACE("%p %x\n", This
, libFlags
);
9007 This
->libflags
= libFlags
;
9012 typedef struct tagWMSFT_SegContents
{
9015 } WMSFT_SegContents
;
9017 typedef struct tagWMSFT_TLBFile
{
9019 WMSFT_SegContents typeinfo_seg
;
9020 WMSFT_SegContents impfile_seg
;
9021 WMSFT_SegContents impinfo_seg
;
9022 WMSFT_SegContents ref_seg
;
9023 WMSFT_SegContents guidhash_seg
;
9024 WMSFT_SegContents guid_seg
;
9025 WMSFT_SegContents namehash_seg
;
9026 WMSFT_SegContents name_seg
;
9027 WMSFT_SegContents string_seg
;
9028 WMSFT_SegContents typdesc_seg
;
9029 WMSFT_SegContents arraydesc_seg
;
9030 WMSFT_SegContents custdata_seg
;
9031 WMSFT_SegContents cdguids_seg
;
9033 WMSFT_SegContents aux_seg
;
9036 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9037 WMSFT_TLBFile
*file
)
9043 file
->string_seg
.len
= 0;
9044 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9047 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9049 return E_UNEXPECTED
;
9051 size
+= sizeof(INT16
);
9053 size
= (size
+ 4) & ~0x3;
9057 file
->string_seg
.len
+= size
;
9059 /* temporarily use str->offset to store the length of the aligned,
9060 * converted string */
9064 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
9067 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9070 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
9071 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9073 heap_free(file
->string_seg
.data
);
9074 return E_UNEXPECTED
;
9077 *((INT16
*)data
) = size
;
9079 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9083 str
->offset
= last_offs
;
9090 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9091 WMSFT_TLBFile
*file
)
9096 MSFT_NameIntro
*last_intro
= NULL
;
9098 file
->header
.nametablecount
= 0;
9099 file
->header
.nametablechars
= 0;
9101 file
->name_seg
.len
= 0;
9102 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9105 size
= strlenW(str
->str
);
9106 file
->header
.nametablechars
+= size
;
9107 file
->header
.nametablecount
++;
9109 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9111 return E_UNEXPECTED
;
9113 size
+= sizeof(MSFT_NameIntro
);
9115 size
= (size
+ 4) & ~0x3;
9119 file
->name_seg
.len
+= size
;
9121 /* temporarily use str->offset to store the length of the aligned,
9122 * converted string */
9126 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9127 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
9130 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9132 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9134 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
9135 data
+ sizeof(MSFT_NameIntro
),
9136 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9138 heap_free(file
->name_seg
.data
);
9139 return E_UNEXPECTED
;
9141 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9143 intro
->hreftype
= -1; /* TODO? */
9144 intro
->namelen
= size
& 0xFF;
9145 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9146 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9147 intro
->namelen
|= hash
<< 16;
9148 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9149 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9151 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9152 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9154 /* update str->offset to actual value to use in other
9155 * compilation functions that require positions within
9156 * the string table */
9160 str
->offset
= last_offs
;
9165 last_intro
->hreftype
= 0; /* last one is 0? */
9170 static inline int hash_guid(GUID
*guid
)
9174 for (i
= 0; i
< 8; i
++)
9175 hash
^= ((const short *)guid
)[i
];
9180 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9183 MSFT_GuidEntry
*entry
;
9185 int hash_key
, *guidhashtab
;
9187 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9188 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9190 entry
= file
->guid_seg
.data
;
9192 guidhashtab
= file
->guidhash_seg
.data
;
9193 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9194 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9195 entry
->hreftype
= guid
->hreftype
;
9197 hash_key
= hash_guid(&guid
->guid
);
9198 entry
->next_hash
= guidhashtab
[hash_key
];
9199 guidhashtab
[hash_key
] = offs
;
9201 guid
->offset
= offs
;
9202 offs
+= sizeof(MSFT_GuidEntry
);
9209 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9212 VARTYPE arg_type
= V_VT(value
);
9215 DWORD ret
= file
->custdata_seg
.len
;
9217 if(arg_type
== VT_INT
)
9219 if(arg_type
== VT_UINT
)
9223 if(V_VT(value
) != arg_type
) {
9224 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9226 ERR("VariantChangeType failed: %08x\n", hres
);
9231 /* Check if default value can be stored in-place */
9236 if(V_UI4(&v
) > 0x3ffffff)
9249 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9252 /* have to allocate space in custdata_seg */
9261 /* Construct the data to be allocated */
9264 if(file
->custdata_seg
.data
){
9265 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9266 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9267 file
->custdata_seg
.len
+= sizeof(int) * 2;
9269 file
->custdata_seg
.len
= sizeof(int) * 2;
9270 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9273 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9274 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9276 /* TODO: Check if the encoded data is already present in custdata_seg */
9282 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9285 if(file
->custdata_seg
.data
){
9286 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9287 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9288 file
->custdata_seg
.len
+= len
;
9290 file
->custdata_seg
.len
= len
;
9291 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9294 *((unsigned short *)data
) = V_VT(value
);
9295 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9296 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9297 if(V_BSTR(&v
)[i
] <= 0x7f)
9298 data
[i
+6] = V_BSTR(&v
)[i
];
9302 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9303 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9306 /* TODO: Check if the encoded data is already present in custdata_seg */
9311 FIXME("Argument type not yet handled\n");
9316 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9318 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9320 DWORD offs
= file
->arraydesc_seg
.len
;
9324 /* TODO: we should check for duplicates, but that's harder because each
9325 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9326 * at the library-level) */
9328 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9329 if(!file
->arraydesc_seg
.data
)
9330 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9332 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9333 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9335 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9336 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9337 for(i
= 0; i
< desc
->cDims
; ++i
){
9338 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9339 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9345 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9351 VARTYPE vt
, subtype
;
9362 vt
= desc
->vt
& VT_TYPEMASK
;
9364 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9366 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9367 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9369 *out_size
+= 2 * sizeof(DWORD
);
9370 }else if(vt
== VT_CARRAY
){
9371 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9372 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9374 }else if(vt
== VT_USERDEFINED
){
9375 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9376 encoded
[1] = desc
->u
.hreftype
;
9377 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9379 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9397 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9400 data
= file
->typdesc_seg
.data
;
9401 while(offs
< file
->typdesc_seg
.len
){
9402 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9404 offs
+= sizeof(encoded
);
9407 file
->typdesc_seg
.len
+= sizeof(encoded
);
9408 if(!file
->typdesc_seg
.data
)
9409 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9411 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9413 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9418 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9420 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9421 DWORD ret
= cdguids_seg
->len
, offs
;
9422 MSFT_CDGuid
*cdguid
;
9425 if(list_empty(custdata_list
))
9428 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9429 if(!cdguids_seg
->data
){
9430 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9432 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9433 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9436 offs
= ret
+ sizeof(MSFT_CDGuid
);
9437 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9438 cdguid
->GuidOffset
= cd
->guid
->offset
;
9439 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9440 cdguid
->next
= offs
;
9441 offs
+= sizeof(MSFT_CDGuid
);
9451 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9452 WMSFT_TLBFile
*file
)
9454 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9455 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9456 MSFT_VarRecord
*varrecord
;
9457 MSFT_FuncRecord
*funcrecord
;
9459 DWORD
*name
, *offsets
, offs
;
9461 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9462 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9464 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9466 /* optional fields */
9467 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9468 if(!list_empty(&desc
->custdata_list
))
9469 recorded_size
+= 7 * sizeof(INT
);
9470 else if(desc
->HelpStringContext
!= 0)
9471 recorded_size
+= 6 * sizeof(INT
);
9473 else if(desc
->Entry
)
9474 recorded_size
+= 3 * sizeof(INT
);
9475 else if(desc
->HelpString
)
9476 recorded_size
+= 2 * sizeof(INT
);
9477 else if(desc
->helpcontext
)
9478 recorded_size
+= sizeof(INT
);
9480 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9482 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9483 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9484 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9489 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9492 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9493 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9495 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9497 /* optional fields */
9498 if(desc
->HelpStringContext
!= 0)
9499 recorded_size
+= 5 * sizeof(INT
);
9500 else if(!list_empty(&desc
->custdata_list
))
9501 recorded_size
+= 4 * sizeof(INT
);
9503 else if(desc
->HelpString
)
9504 recorded_size
+= 2 * sizeof(INT
);
9505 else if(desc
->HelpContext
!= 0)
9506 recorded_size
+= sizeof(INT
);
9508 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9511 if(!recorded_size
&& !extra_size
)
9514 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9516 aux_seg
->len
+= recorded_size
+ extra_size
;
9518 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9521 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9523 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9525 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9527 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9530 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9531 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9532 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9533 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9535 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9536 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9537 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9538 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9541 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9546 * ^has_param_defaults
9547 * ^oEntry_is_intresource
9549 funcrecord
->FKCCIC
=
9550 desc
->funcdesc
.funckind
|
9551 (desc
->funcdesc
.invkind
<< 3) |
9552 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9553 (desc
->funcdesc
.callconv
<< 8);
9555 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9556 funcrecord
->FKCCIC
|= 0x2000;
9558 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9559 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9560 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9561 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9564 if(paramdefault_size
> 0)
9565 funcrecord
->FKCCIC
|= 0x1000;
9567 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9568 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9570 /* optional fields */
9572 if(!list_empty(&desc
->custdata_list
)){
9573 size
+= 7 * sizeof(INT
);
9574 funcrecord
->HelpContext
= desc
->helpcontext
;
9575 if(desc
->HelpString
)
9576 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9578 funcrecord
->oHelpString
= -1;
9580 funcrecord
->oEntry
= -1;
9581 else if(IS_INTRESOURCE(desc
->Entry
))
9582 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9584 funcrecord
->oEntry
= desc
->Entry
->offset
;
9585 funcrecord
->res9
= -1;
9586 funcrecord
->resA
= -1;
9587 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9588 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9589 }else if(desc
->HelpStringContext
!= 0){
9590 size
+= 6 * sizeof(INT
);
9591 funcrecord
->HelpContext
= desc
->helpcontext
;
9592 if(desc
->HelpString
)
9593 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9595 funcrecord
->oHelpString
= -1;
9597 funcrecord
->oEntry
= -1;
9598 else if(IS_INTRESOURCE(desc
->Entry
))
9599 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9601 funcrecord
->oEntry
= desc
->Entry
->offset
;
9602 funcrecord
->res9
= -1;
9603 funcrecord
->resA
= -1;
9604 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9605 }else if(desc
->Entry
){
9606 size
+= 3 * sizeof(INT
);
9607 funcrecord
->HelpContext
= desc
->helpcontext
;
9608 if(desc
->HelpString
)
9609 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9611 funcrecord
->oHelpString
= -1;
9613 funcrecord
->oEntry
= -1;
9614 else if(IS_INTRESOURCE(desc
->Entry
))
9615 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9617 funcrecord
->oEntry
= desc
->Entry
->offset
;
9618 }else if(desc
->HelpString
){
9619 size
+= 2 * sizeof(INT
);
9620 funcrecord
->HelpContext
= desc
->helpcontext
;
9621 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9622 }else if(desc
->helpcontext
){
9623 size
+= sizeof(INT
);
9624 funcrecord
->HelpContext
= desc
->helpcontext
;
9627 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9628 size
+= paramdefault_size
;
9630 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9631 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9633 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9634 if(desc
->pParamDesc
[j
].Name
)
9635 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9638 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9640 if(paramdefault_size
){
9641 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9642 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9643 else if(paramdefault_size
)
9648 size
+= sizeof(MSFT_ParameterInfo
);
9651 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9657 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9660 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9661 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9662 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9663 DWORD size
= 5 * sizeof(INT
);
9665 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9666 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9667 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9668 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9670 if(desc
->vardesc
.varkind
== VAR_CONST
){
9671 varrecord
->vardescsize
+= sizeof(VARIANT
);
9672 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9674 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9677 if(desc
->HelpStringContext
!= 0){
9678 size
+= 5 * sizeof(INT
);
9679 varrecord
->HelpContext
= desc
->HelpContext
;
9680 if(desc
->HelpString
)
9681 varrecord
->HelpString
= desc
->HelpString
->offset
;
9683 varrecord
->HelpString
= -1;
9684 varrecord
->res9
= -1;
9685 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9686 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9687 }else if(!list_empty(&desc
->custdata_list
)){
9688 size
+= 4 * sizeof(INT
);
9689 varrecord
->HelpContext
= desc
->HelpContext
;
9690 if(desc
->HelpString
)
9691 varrecord
->HelpString
= desc
->HelpString
->offset
;
9693 varrecord
->HelpString
= -1;
9694 varrecord
->res9
= -1;
9695 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9696 }else if(desc
->HelpString
){
9697 size
+= 2 * sizeof(INT
);
9698 varrecord
->HelpContext
= desc
->HelpContext
;
9699 if(desc
->HelpString
)
9700 varrecord
->HelpString
= desc
->HelpString
->offset
;
9702 varrecord
->HelpString
= -1;
9703 }else if(desc
->HelpContext
!= 0){
9704 size
+= sizeof(INT
);
9705 varrecord
->HelpContext
= desc
->HelpContext
;
9708 varrecord
->Info
= size
| (i
<< 16);
9714 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9717 memid
= (MEMBERID
*)varrecord
;
9718 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9719 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9720 *memid
= desc
->funcdesc
.memid
;
9723 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9724 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9725 *memid
= desc
->vardesc
.memid
;
9729 name
= (UINT
*)memid
;
9730 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9731 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9733 *name
= desc
->Name
->offset
;
9738 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9739 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9741 *name
= desc
->Name
->offset
;
9750 typedef struct tagWMSFT_RefChunk
{
9757 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9759 DWORD offs
= file
->ref_seg
.len
, i
;
9760 WMSFT_RefChunk
*chunk
;
9762 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9763 if(!file
->ref_seg
.data
)
9764 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9766 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9768 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9770 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9771 chunk
->href
= info
->impltypes
[i
].hRef
;
9772 chunk
->res04
= info
->impltypes
[i
].implflags
;
9774 if(i
< info
->typeattr
.cImplTypes
- 1)
9775 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9784 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9788 size
= sizeof(MSFT_TypeInfoBase
);
9791 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9792 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9793 base
->typekind
= TKIND_DISPATCH
;
9795 base
->typekind
= info
->typeattr
.typekind
;
9796 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9797 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
9798 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9803 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
9809 base
->posguid
= info
->guid
->offset
;
9812 base
->flags
= info
->typeattr
.wTypeFlags
;
9814 base
->NameOffset
= info
->Name
->offset
;
9816 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9817 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9819 base
->NameOffset
= -1;
9821 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
9823 base
->docstringoffs
= info
->DocString
->offset
;
9825 base
->docstringoffs
= -1;
9826 base
->helpstringcontext
= info
->dwHelpStringContext
;
9827 base
->helpcontext
= info
->dwHelpContext
;
9828 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9829 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
9830 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
9831 base
->size
= info
->typeattr
.cbSizeInstance
;
9832 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
9833 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9834 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
9835 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9836 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
9838 base
->datatype1
= info
->DllName
->offset
;
9840 base
->datatype1
= -1;
9842 if(info
->typeattr
.cImplTypes
> 0)
9843 base
->datatype1
= info
->impltypes
[0].hRef
;
9845 base
->datatype1
= -1;
9847 base
->datatype2
= index
; /* FIXME: i think there's more here */
9855 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9859 file
->typeinfo_seg
.len
= 0;
9860 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9861 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9862 *junk
= file
->typeinfo_seg
.len
;
9864 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9867 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9868 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9870 file
->aux_seg
.len
= 0;
9871 file
->aux_seg
.data
= NULL
;
9873 file
->typeinfo_seg
.len
= 0;
9874 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9875 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9876 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9877 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9881 typedef struct tagWMSFT_ImpFile
{
9887 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9890 WMSFT_ImpFile
*impfile
;
9892 DWORD last_offs
= 0;
9894 file
->impfile_seg
.len
= 0;
9895 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9899 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9903 path
= implib
->name
;
9904 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9906 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9909 size
+= sizeof(INT16
);
9911 size
= (size
+ 4) & ~0x3;
9915 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9918 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9920 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9921 int strlen
= 0, size
;
9923 impfile
= (WMSFT_ImpFile
*)data
;
9924 impfile
->guid_offs
= implib
->guid
->offset
;
9925 impfile
->lcid
= implib
->lcid
;
9926 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9928 data
+= sizeof(WMSFT_ImpFile
);
9931 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9935 path
= implib
->name
;
9936 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9937 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9939 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9942 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9944 size
= strlen
+ sizeof(INT16
);
9946 size
= (size
+ 4) & ~0x3;
9949 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9952 implib
->offset
= last_offs
;
9953 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9957 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9960 TLBRefType
*ref_type
;
9963 WMSFT_compile_impfile(This
, file
);
9965 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9966 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9968 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9969 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9970 if(ref_type
->index
== TLB_REF_USE_GUID
){
9971 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9972 info
->oGuid
= ref_type
->guid
->offset
;
9974 info
->oGuid
= ref_type
->index
;
9975 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9981 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9983 file
->guidhash_seg
.len
= 0x80;
9984 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9985 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9988 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9990 file
->namehash_seg
.len
= 0x200;
9991 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9992 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9995 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9997 if(contents
&& contents
->len
){
9998 segdir
->offset
= *running_offset
;
9999 segdir
->length
= contents
->len
;
10000 *running_offset
+= segdir
->length
;
10002 segdir
->offset
= -1;
10003 segdir
->length
= 0;
10006 /* TODO: do these ever change? */
10007 segdir
->res08
= -1;
10008 segdir
->res0c
= 0xf;
10011 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10015 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10018 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10022 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10024 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10025 base
->memoffset
+= file_len
;
10032 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10034 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
10035 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
10036 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
10037 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
10038 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
10039 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
10040 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
10041 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
10042 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
10043 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
10044 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
10045 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
10046 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
10047 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
10050 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10052 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10053 WMSFT_TLBFile file
;
10054 DWORD written
, junk_size
, junk_offs
, running_offset
;
10061 TRACE("%p\n", This
);
10063 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10064 if(This
->typeinfos
[i
]->needs_layout
)
10065 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10067 memset(&file
, 0, sizeof(file
));
10069 file
.header
.magic1
= 0x5446534D;
10070 file
.header
.magic2
= 0x00010002;
10071 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10072 file
.header
.lcid2
= This
->set_lcid
;
10073 file
.header
.varflags
= 0x40 | This
->syskind
;
10074 if (This
->HelpFile
)
10075 file
.header
.varflags
|= 0x10;
10076 if (This
->HelpStringDll
)
10077 file
.header
.varflags
|= HELPDLLFLAG
;
10078 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10079 file
.header
.flags
= This
->libflags
;
10080 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10081 file
.header
.helpcontext
= This
->dwHelpContext
;
10082 file
.header
.res44
= 0x20;
10083 file
.header
.res48
= 0x80;
10084 file
.header
.dispatchpos
= This
->dispatch_href
;
10086 WMSFT_compile_namehash(This
, &file
);
10087 /* do name and string compilation to get offsets for other compilations */
10088 hres
= WMSFT_compile_names(This
, &file
);
10090 WMSFT_free_file(&file
);
10094 hres
= WMSFT_compile_strings(This
, &file
);
10096 WMSFT_free_file(&file
);
10100 WMSFT_compile_guidhash(This
, &file
);
10101 hres
= WMSFT_compile_guids(This
, &file
);
10103 WMSFT_free_file(&file
);
10108 file
.header
.helpfile
= This
->HelpFile
->offset
;
10110 file
.header
.helpfile
= -1;
10112 if(This
->DocString
)
10113 file
.header
.helpstring
= This
->DocString
->offset
;
10115 file
.header
.helpstring
= -1;
10117 /* do some more segment compilation */
10118 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10119 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10122 file
.header
.NameOffset
= This
->Name
->offset
;
10124 file
.header
.NameOffset
= -1;
10126 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10129 file
.header
.posguid
= This
->guid
->offset
;
10131 file
.header
.posguid
= -1;
10133 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10134 if(file
.header
.varflags
& HELPDLLFLAG
)
10135 junk_size
+= sizeof(DWORD
);
10137 junk
= heap_alloc_zero(junk_size
);
10138 if(file
.header
.varflags
& HELPDLLFLAG
){
10139 *junk
= This
->HelpStringDll
->offset
;
10148 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10149 WMSFT_compile_impinfo(This
, &file
);
10151 running_offset
= 0;
10153 TRACE("header at: 0x%x\n", running_offset
);
10154 running_offset
+= sizeof(file
.header
);
10156 TRACE("junk at: 0x%x\n", running_offset
);
10157 running_offset
+= junk_size
;
10159 TRACE("segdir at: 0x%x\n", running_offset
);
10160 running_offset
+= sizeof(file
.segdir
);
10162 TRACE("typeinfo at: 0x%x\n", running_offset
);
10163 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10165 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10166 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10168 TRACE("guidtab at: 0x%x\n", running_offset
);
10169 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10171 TRACE("reftab at: 0x%x\n", running_offset
);
10172 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10174 TRACE("impinfo at: 0x%x\n", running_offset
);
10175 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10177 TRACE("impfiles at: 0x%x\n", running_offset
);
10178 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10180 TRACE("namehashtab at: 0x%x\n", running_offset
);
10181 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10183 TRACE("nametab at: 0x%x\n", running_offset
);
10184 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10186 TRACE("stringtab at: 0x%x\n", running_offset
);
10187 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10189 TRACE("typdesc at: 0x%x\n", running_offset
);
10190 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10192 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10193 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10195 TRACE("custdata at: 0x%x\n", running_offset
);
10196 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10198 TRACE("cdguids at: 0x%x\n", running_offset
);
10199 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10201 TRACE("res0e at: 0x%x\n", running_offset
);
10202 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10204 TRACE("res0f at: 0x%x\n", running_offset
);
10205 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10207 TRACE("aux_seg at: 0x%x\n", running_offset
);
10209 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10211 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10212 FILE_ATTRIBUTE_NORMAL
, 0);
10213 if (outfile
== INVALID_HANDLE_VALUE
){
10214 WMSFT_free_file(&file
);
10216 return TYPE_E_IOERROR
;
10219 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10221 WMSFT_free_file(&file
);
10222 CloseHandle(outfile
);
10224 return TYPE_E_IOERROR
;
10227 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10230 WMSFT_free_file(&file
);
10231 CloseHandle(outfile
);
10232 return TYPE_E_IOERROR
;
10235 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10237 WMSFT_free_file(&file
);
10238 CloseHandle(outfile
);
10239 return TYPE_E_IOERROR
;
10242 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10243 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10244 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10245 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10246 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10247 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10248 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10249 WMSFT_write_segment(outfile
, &file
.name_seg
);
10250 WMSFT_write_segment(outfile
, &file
.string_seg
);
10251 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10252 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10253 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10254 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10255 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10257 WMSFT_free_file(&file
);
10259 CloseHandle(outfile
);
10264 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10267 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10268 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10272 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10273 REFGUID guid
, VARIANT
*varVal
)
10275 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10278 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10280 if (!guid
|| !varVal
)
10281 return E_INVALIDARG
;
10283 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10285 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10288 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10289 ULONG helpStringContext
)
10291 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10292 FIXME("%p %u - stub\n", This
, helpStringContext
);
10296 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10299 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10300 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10303 return E_INVALIDARG
;
10305 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10310 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10311 ICreateTypeLib2_fnQueryInterface
,
10312 ICreateTypeLib2_fnAddRef
,
10313 ICreateTypeLib2_fnRelease
,
10314 ICreateTypeLib2_fnCreateTypeInfo
,
10315 ICreateTypeLib2_fnSetName
,
10316 ICreateTypeLib2_fnSetVersion
,
10317 ICreateTypeLib2_fnSetGuid
,
10318 ICreateTypeLib2_fnSetDocString
,
10319 ICreateTypeLib2_fnSetHelpFileName
,
10320 ICreateTypeLib2_fnSetHelpContext
,
10321 ICreateTypeLib2_fnSetLcid
,
10322 ICreateTypeLib2_fnSetLibFlags
,
10323 ICreateTypeLib2_fnSaveAllChanges
,
10324 ICreateTypeLib2_fnDeleteTypeInfo
,
10325 ICreateTypeLib2_fnSetCustData
,
10326 ICreateTypeLib2_fnSetHelpStringContext
,
10327 ICreateTypeLib2_fnSetHelpStringDll
10330 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10331 REFIID riid
, void **object
)
10333 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10335 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10338 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10340 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10342 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10345 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10347 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10349 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10352 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10355 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10357 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10359 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10364 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10367 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10371 TRACE("%p %x\n", This
, typeFlags
);
10373 if (typeFlags
& TYPEFLAG_FDUAL
) {
10374 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10376 ITypeInfo
*dispatch
;
10380 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10384 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10385 ITypeLib_Release(stdole
);
10389 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10390 ITypeInfo_Release(dispatch
);
10395 old_flags
= This
->typeattr
.wTypeFlags
;
10396 This
->typeattr
.wTypeFlags
= typeFlags
;
10398 hres
= ICreateTypeInfo2_LayOut(iface
);
10399 if (FAILED(hres
)) {
10400 This
->typeattr
.wTypeFlags
= old_flags
;
10407 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10410 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10412 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10415 return E_INVALIDARG
;
10417 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10422 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10425 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10427 TRACE("%p %d\n", This
, helpContext
);
10429 This
->dwHelpContext
= helpContext
;
10434 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10435 WORD majorVerNum
, WORD minorVerNum
)
10437 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10439 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10441 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10442 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10447 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10448 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10450 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10452 ITypeLib
*container
;
10453 TLBRefType
*ref_type
;
10455 TYPEATTR
*typeattr
;
10459 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10461 if (!typeInfo
|| !refType
)
10462 return E_INVALIDARG
;
10464 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10468 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10469 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10471 ITypeLib_Release(container
);
10473 *refType
= target
->hreftype
;
10478 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10479 if (FAILED(hres
)) {
10480 ITypeLib_Release(container
);
10484 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10485 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10486 implib
->lcid
== libattr
->lcid
&&
10487 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10488 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10492 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10493 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10495 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10496 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10497 implib
->name
= SysAllocString(our_container
->path
);
10499 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10500 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10502 implib
->name
= NULL
;
10503 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10507 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10508 implib
->lcid
= libattr
->lcid
;
10509 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10510 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10512 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10515 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10516 ITypeLib_Release(container
);
10518 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10523 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10524 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10525 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10526 ref_type
->tkind
== typeattr
->typekind
)
10531 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10532 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10534 ref_type
->tkind
= typeattr
->typekind
;
10535 ref_type
->pImpTLInfo
= implib
;
10536 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10538 ref_type
->index
= TLB_REF_USE_GUID
;
10540 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10542 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10545 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10547 *refType
= ref_type
->reference
| 0x1;
10549 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10550 This
->pTypeLib
->dispatch_href
= *refType
;
10555 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10556 UINT index
, FUNCDESC
*funcDesc
)
10558 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10559 TLBFuncDesc tmp_func_desc
, *func_desc
;
10564 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10566 if (!funcDesc
|| funcDesc
->oVft
& 3)
10567 return E_INVALIDARG
;
10569 switch (This
->typeattr
.typekind
) {
10571 if (funcDesc
->funckind
!= FUNC_STATIC
)
10572 return TYPE_E_BADMODULEKIND
;
10574 case TKIND_DISPATCH
:
10575 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10576 return TYPE_E_BADMODULEKIND
;
10579 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10580 return TYPE_E_BADMODULEKIND
;
10583 if (index
> This
->typeattr
.cFuncs
)
10584 return TYPE_E_ELEMENTNOTFOUND
;
10586 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10587 !funcDesc
->cParams
)
10588 return TYPE_E_INCONSISTENTPROPFUNCS
;
10591 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10592 funcDesc
->oVft
% 8 != 0)
10593 return E_INVALIDARG
;
10596 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10597 TLBFuncDesc_Constructor(&tmp_func_desc
);
10599 tmp_func_desc
.funcdesc
= *funcDesc
;
10601 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10602 tmp_func_desc
.funcdesc
.oVft
|= 1;
10604 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10605 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10606 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10608 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10609 tmp_func_desc
.funcdesc
.cScodes
= 0;
10612 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10613 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10614 buf_size
+= sizeof(ELEMDESC
);
10615 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10617 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10618 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10620 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10621 if (FAILED(hres
)) {
10622 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10623 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10627 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10628 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10629 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10630 if (FAILED(hres
)) {
10631 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10632 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10635 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10636 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10637 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10638 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10639 if (FAILED(hres
)) {
10640 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10641 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10647 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10649 if (This
->funcdescs
) {
10650 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10651 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10653 if (index
< This
->typeattr
.cFuncs
) {
10654 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10655 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10656 func_desc
= This
->funcdescs
+ index
;
10658 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10660 /* move custdata lists to the new memory location */
10661 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10663 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10664 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10665 list_init(&fd
->custdata_list
);
10667 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10668 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10673 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10675 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10676 list_init(&func_desc
->custdata_list
);
10678 ++This
->typeattr
.cFuncs
;
10680 This
->needs_layout
= TRUE
;
10685 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10686 UINT index
, HREFTYPE refType
)
10688 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10689 TLBImplType
*impl_type
;
10692 TRACE("%p %u %d\n", This
, index
, refType
);
10694 switch(This
->typeattr
.typekind
){
10695 case TKIND_COCLASS
: {
10697 FIXME("Unhandled index: -1\n");
10701 if(index
!= This
->typeattr
.cImplTypes
)
10702 return TYPE_E_ELEMENTNOTFOUND
;
10706 case TKIND_INTERFACE
:
10707 case TKIND_DISPATCH
:
10708 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10709 return TYPE_E_ELEMENTNOTFOUND
;
10712 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10716 if (This
->impltypes
){
10719 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10720 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10722 if (index
< This
->typeattr
.cImplTypes
) {
10723 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10724 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10725 impl_type
= This
->impltypes
+ index
;
10727 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10729 /* move custdata lists to the new memory location */
10730 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10732 TLBImplType
*it
= &This
->impltypes
[i
];
10733 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10734 list_init(&it
->custdata_list
);
10736 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10737 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10742 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10744 memset(impl_type
, 0, sizeof(TLBImplType
));
10745 TLBImplType_Constructor(impl_type
);
10746 impl_type
->hRef
= refType
;
10748 ++This
->typeattr
.cImplTypes
;
10750 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10751 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10753 hres
= ICreateTypeInfo2_LayOut(iface
);
10760 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10761 UINT index
, INT implTypeFlags
)
10763 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10764 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10766 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10768 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10769 return TYPE_E_BADMODULEKIND
;
10771 if (index
>= This
->typeattr
.cImplTypes
)
10772 return TYPE_E_ELEMENTNOTFOUND
;
10774 impl_type
->implflags
= implTypeFlags
;
10779 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10782 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10784 TRACE("%p %d\n", This
, alignment
);
10786 This
->typeattr
.cbAlignment
= alignment
;
10791 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10794 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10796 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10799 return E_INVALIDARG
;
10801 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10803 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10808 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10809 UINT index
, VARDESC
*varDesc
)
10811 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10812 TLBVarDesc
*var_desc
;
10814 TRACE("%p %u %p\n", This
, index
, varDesc
);
10816 if (This
->vardescs
){
10819 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10820 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
10822 if (index
< This
->typeattr
.cVars
) {
10823 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10824 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
10825 var_desc
= This
->vardescs
+ index
;
10827 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
10829 /* move custdata lists to the new memory location */
10830 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
10832 TLBVarDesc
*var
= &This
->vardescs
[i
];
10833 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10834 list_init(&var
->custdata_list
);
10836 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10837 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10842 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10844 TLBVarDesc_Constructor(var_desc
);
10845 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10846 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10848 ++This
->typeattr
.cVars
;
10850 This
->needs_layout
= TRUE
;
10855 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10856 UINT index
, LPOLESTR
*names
, UINT numNames
)
10858 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10859 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10862 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10865 return E_INVALIDARG
;
10867 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
10868 return TYPE_E_ELEMENTNOTFOUND
;
10870 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10871 if(numNames
> func_desc
->funcdesc
.cParams
)
10872 return TYPE_E_ELEMENTNOTFOUND
;
10874 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10875 return TYPE_E_ELEMENTNOTFOUND
;
10877 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
10878 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10879 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10880 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10881 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10882 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10884 return TYPE_E_AMBIGUOUSNAME
;
10888 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10890 for (i
= 1; i
< numNames
; ++i
) {
10891 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10892 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10898 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10899 UINT index
, LPOLESTR name
)
10901 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10903 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10906 return E_INVALIDARG
;
10908 if(index
>= This
->typeattr
.cVars
)
10909 return TYPE_E_ELEMENTNOTFOUND
;
10911 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10915 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10916 TYPEDESC
*tdescAlias
)
10918 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10921 TRACE("%p %p\n", This
, tdescAlias
);
10924 return E_INVALIDARG
;
10926 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
10927 return TYPE_E_BADMODULEKIND
;
10929 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
10933 heap_free(This
->tdescAlias
);
10934 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10935 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10940 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10941 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10943 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10944 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10948 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10949 UINT index
, LPOLESTR docString
)
10951 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10952 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10954 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10957 return E_INVALIDARG
;
10959 if(index
>= This
->typeattr
.cFuncs
)
10960 return TYPE_E_ELEMENTNOTFOUND
;
10962 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10967 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10968 UINT index
, LPOLESTR docString
)
10970 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10971 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10973 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10976 return E_INVALIDARG
;
10978 if(index
>= This
->typeattr
.cVars
)
10979 return TYPE_E_ELEMENTNOTFOUND
;
10981 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10986 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10987 UINT index
, DWORD helpContext
)
10989 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10990 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10992 TRACE("%p %u %d\n", This
, index
, helpContext
);
10994 if(index
>= This
->typeattr
.cFuncs
)
10995 return TYPE_E_ELEMENTNOTFOUND
;
10997 func_desc
->helpcontext
= helpContext
;
11002 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
11003 UINT index
, DWORD helpContext
)
11005 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11006 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11008 TRACE("%p %u %d\n", This
, index
, helpContext
);
11010 if(index
>= This
->typeattr
.cVars
)
11011 return TYPE_E_ELEMENTNOTFOUND
;
11013 var_desc
->HelpContext
= helpContext
;
11018 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
11019 UINT index
, BSTR bstrMops
)
11021 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11022 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
11026 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
11029 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11031 TRACE("%p %p\n", This
, idlDesc
);
11034 return E_INVALIDARG
;
11036 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11037 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11042 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11044 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11046 TLBFuncDesc
*func_desc
;
11047 UINT user_vft
= 0, i
, depth
= 0;
11048 HRESULT hres
= S_OK
;
11050 TRACE("%p\n", This
);
11052 This
->needs_layout
= FALSE
;
11054 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
11058 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11063 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11065 if (SUCCEEDED(hres
)) {
11066 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11068 if (SUCCEEDED(hres
)) {
11069 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11070 if (FAILED(hres
)) {
11071 ITypeInfo_Release(inh
);
11072 ITypeInfo_Release(tinfo
);
11075 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11076 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11080 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11081 if(SUCCEEDED(hres
)){
11083 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11084 if(SUCCEEDED(hres
)){
11085 ITypeInfo_Release(inh
);
11089 }while(SUCCEEDED(hres
));
11092 ITypeInfo_Release(inh
);
11093 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11094 This
->typeattr
.cbSizeVft
= 0;
11097 ITypeInfo_Release(tinfo
);
11100 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11101 This
->typeattr
.cbSizeVft
= 0;
11104 ITypeInfo_Release(tinfo
);
11107 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11108 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11110 This
->typeattr
.cbSizeVft
= 0;
11112 func_desc
= This
->funcdescs
;
11114 while (i
< This
->typeattr
.cFuncs
) {
11115 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11116 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11118 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11119 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11121 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11123 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11126 BOOL reset
= FALSE
;
11128 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11130 iter
= This
->funcdescs
;
11131 while (j
< This
->typeattr
.cFuncs
) {
11132 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11134 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11137 ++func_desc
->funcdesc
.memid
;
11138 iter
= This
->funcdescs
;
11151 if (user_vft
> This
->typeattr
.cbSizeVft
)
11152 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11154 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11155 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11156 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11158 BOOL reset
= FALSE
;
11161 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11163 iter
= This
->vardescs
;
11164 while (j
< This
->typeattr
.cVars
) {
11165 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11167 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11170 ++var_desc
->vardesc
.memid
;
11171 iter
= This
->vardescs
;
11181 ITypeInfo_Release(tinfo
);
11185 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11188 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11189 FIXME("%p %u - stub\n", This
, index
);
11193 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11194 MEMBERID memid
, INVOKEKIND invKind
)
11196 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11197 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11201 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11204 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11205 FIXME("%p %u - stub\n", This
, index
);
11209 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11212 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11213 FIXME("%p %x - stub\n", This
, memid
);
11217 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11220 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11221 FIXME("%p %u - stub\n", This
, index
);
11225 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11226 REFGUID guid
, VARIANT
*varVal
)
11230 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11232 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11234 if (!guid
|| !varVal
)
11235 return E_INVALIDARG
;
11237 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11239 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11242 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11243 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11245 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11246 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11250 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11251 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11253 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11254 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11258 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11259 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11261 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11262 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11266 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11267 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11269 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11270 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11274 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11275 ULONG helpStringContext
)
11277 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11279 TRACE("%p %u\n", This
, helpStringContext
);
11281 This
->dwHelpStringContext
= helpStringContext
;
11286 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11287 UINT index
, ULONG helpStringContext
)
11289 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11290 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11294 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11295 UINT index
, ULONG helpStringContext
)
11297 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11298 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11302 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11304 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11305 FIXME("%p - stub\n", This
);
11309 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11312 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11314 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11317 return E_INVALIDARG
;
11319 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11324 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11325 ICreateTypeInfo2_fnQueryInterface
,
11326 ICreateTypeInfo2_fnAddRef
,
11327 ICreateTypeInfo2_fnRelease
,
11328 ICreateTypeInfo2_fnSetGuid
,
11329 ICreateTypeInfo2_fnSetTypeFlags
,
11330 ICreateTypeInfo2_fnSetDocString
,
11331 ICreateTypeInfo2_fnSetHelpContext
,
11332 ICreateTypeInfo2_fnSetVersion
,
11333 ICreateTypeInfo2_fnAddRefTypeInfo
,
11334 ICreateTypeInfo2_fnAddFuncDesc
,
11335 ICreateTypeInfo2_fnAddImplType
,
11336 ICreateTypeInfo2_fnSetImplTypeFlags
,
11337 ICreateTypeInfo2_fnSetAlignment
,
11338 ICreateTypeInfo2_fnSetSchema
,
11339 ICreateTypeInfo2_fnAddVarDesc
,
11340 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11341 ICreateTypeInfo2_fnSetVarName
,
11342 ICreateTypeInfo2_fnSetTypeDescAlias
,
11343 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11344 ICreateTypeInfo2_fnSetFuncDocString
,
11345 ICreateTypeInfo2_fnSetVarDocString
,
11346 ICreateTypeInfo2_fnSetFuncHelpContext
,
11347 ICreateTypeInfo2_fnSetVarHelpContext
,
11348 ICreateTypeInfo2_fnSetMops
,
11349 ICreateTypeInfo2_fnSetTypeIdldesc
,
11350 ICreateTypeInfo2_fnLayOut
,
11351 ICreateTypeInfo2_fnDeleteFuncDesc
,
11352 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11353 ICreateTypeInfo2_fnDeleteVarDesc
,
11354 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11355 ICreateTypeInfo2_fnDeleteImplType
,
11356 ICreateTypeInfo2_fnSetCustData
,
11357 ICreateTypeInfo2_fnSetFuncCustData
,
11358 ICreateTypeInfo2_fnSetParamCustData
,
11359 ICreateTypeInfo2_fnSetVarCustData
,
11360 ICreateTypeInfo2_fnSetImplTypeCustData
,
11361 ICreateTypeInfo2_fnSetHelpStringContext
,
11362 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11363 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11364 ICreateTypeInfo2_fnInvalidate
,
11365 ICreateTypeInfo2_fnSetName
11368 /******************************************************************************
11369 * ClearCustData (OLEAUT32.171)
11371 * Clear a custom data type's data.
11374 * lpCust [I] The custom data type instance
11379 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11381 if (lpCust
&& lpCust
->cCustData
)
11383 if (lpCust
->prgCustData
)
11387 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11388 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11390 CoTaskMemFree(lpCust
->prgCustData
);
11391 lpCust
->prgCustData
= NULL
;
11393 lpCust
->cCustData
= 0;