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
);
62 #define STATUS_SUCCESS ((NTSTATUS)0x00000000)
63 static BOOL WINAPI
GetFileInformationByHandleEx( HANDLE handle
, FILE_INFO_BY_HANDLE_CLASS
class,
64 LPVOID info
, DWORD size
)
72 case FileStandardInfo
:
74 case FileDispositionInfo
:
75 case FileAllocationInfo
:
76 case FileEndOfFileInfo
:
78 case FileCompressionInfo
:
79 case FileAttributeTagInfo
:
80 case FileIoPriorityHintInfo
:
81 case FileRemoteProtocolInfo
:
82 case FileFullDirectoryInfo
:
83 case FileFullDirectoryRestartInfo
:
85 case FileAlignmentInfo
:
87 case FileIdExtdDirectoryInfo
:
88 case FileIdExtdDirectoryRestartInfo
:
89 FIXME( "%p, %u, %p, %u\n", handle
, class, info
, size
);
90 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
94 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileNameInformation
);
95 if (status
!= STATUS_SUCCESS
)
97 SetLastError( RtlNtStatusToDosError( status
) );
102 case FileIdBothDirectoryRestartInfo
:
103 case FileIdBothDirectoryInfo
:
104 status
= NtQueryDirectoryFile( handle
, NULL
, NULL
, NULL
, &io
, info
, size
,
105 FileIdBothDirectoryInformation
, FALSE
, NULL
,
106 (class == FileIdBothDirectoryRestartInfo
) );
107 if (status
!= STATUS_SUCCESS
)
109 SetLastError( RtlNtStatusToDosError( status
) );
115 SetLastError( ERROR_INVALID_PARAMETER
);
133 WORD type_id
; /* Type identifier */
134 WORD count
; /* Number of resources of this type */
135 DWORD resloader
; /* SetResourceHandler() */
141 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
142 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
143 static void TLB_FreeVarDesc(VARDESC
*);
145 /****************************************************************************
148 * Takes p_iVal (which is in little endian) and returns it
149 * in the host machine's byte order.
151 #ifdef WORDS_BIGENDIAN
152 static WORD
FromLEWord(WORD p_iVal
)
154 return (((p_iVal
& 0x00FF) << 8) |
155 ((p_iVal
& 0xFF00) >> 8));
159 static DWORD
FromLEDWord(DWORD p_iVal
)
161 return (((p_iVal
& 0x000000FF) << 24) |
162 ((p_iVal
& 0x0000FF00) << 8) |
163 ((p_iVal
& 0x00FF0000) >> 8) |
164 ((p_iVal
& 0xFF000000) >> 24));
167 #define FromLEWord(X) (X)
168 #define FromLEDWord(X) (X)
171 #define DISPATCH_HREF_OFFSET 0x01000000
172 #define DISPATCH_HREF_MASK 0xff000000
174 /****************************************************************************
177 * Fix byte order in any structure if necessary
179 #ifdef WORDS_BIGENDIAN
180 static void FromLEWords(void *p_Val
, int p_iSize
)
184 p_iSize
/= sizeof(WORD
);
187 *Val
= FromLEWord(*Val
);
194 static void FromLEDWords(void *p_Val
, int p_iSize
)
198 p_iSize
/= sizeof(DWORD
);
201 *Val
= FromLEDWord(*Val
);
207 #define FromLEWords(X,Y) /*nothing*/
208 #define FromLEDWords(X,Y) /*nothing*/
212 * Find a typelib key which matches a requested maj.min version.
214 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
216 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
220 INT best_maj
= -1, best_min
= -1;
223 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
224 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
226 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
229 len
= sizeof(key_name
);
231 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
235 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
237 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
239 if (*wMaj
== 0xffff && *wMin
== 0xffff)
241 if (v_maj
> best_maj
) best_maj
= v_maj
;
242 if (v_min
> best_min
) best_min
= v_min
;
244 else if (*wMaj
== v_maj
)
251 break; /* exact match */
253 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
256 len
= sizeof(key_name
);
260 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
262 if (*wMaj
== 0xffff && *wMin
== 0xffff)
264 if (best_maj
>= 0 && best_min
>= 0)
272 if (*wMaj
== best_maj
&& best_min
>= 0)
280 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
281 /* buffer must be at least 60 characters long */
282 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
284 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
285 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
287 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
288 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
289 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
293 /* get the path of an interface key, in the form "Interface\\<guid>" */
294 /* buffer must be at least 50 characters long */
295 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
297 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
299 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
300 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
304 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
305 /* buffer must be at least 16 characters long */
306 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
308 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
309 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
310 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
311 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
313 sprintfW( buffer
, LcidFormatW
, lcid
);
316 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
317 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
318 case SYS_WIN64
: strcatW( buffer
, win64W
); break;
320 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
326 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
328 struct tlibredirect_data
342 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
343 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
344 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
346 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
350 WCHAR Path
[MAX_PATH
];
353 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
357 ACTCTX_SECTION_KEYED_DATA data
;
359 data
.cbSize
= sizeof(data
);
360 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
362 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
366 if (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
)
367 return TYPE_E_LIBNOTREGISTERED
;
369 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
370 len
= SearchPathW( NULL
, nameW
, NULL
, sizeof(Path
)/sizeof(WCHAR
), Path
, NULL
);
371 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
373 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
374 *path
= SysAllocString( Path
);
379 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
380 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
382 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
383 if (res
== ERROR_FILE_NOT_FOUND
)
385 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
386 return TYPE_E_LIBNOTREGISTERED
;
388 else if (res
!= ERROR_SUCCESS
)
390 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
391 return TYPE_E_REGISTRYACCESS
;
396 LONG dwPathLen
= sizeof(Path
);
398 get_lcid_subkey( myLCID
, syskind
, buffer
);
400 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
404 else if (myLCID
== lcid
)
406 /* try with sub-langid */
407 myLCID
= SUBLANGID(lcid
);
409 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
411 /* try with system langid */
421 *path
= SysAllocString( Path
);
426 TRACE_(typelib
)("-- 0x%08x\n", hr
);
430 /****************************************************************************
431 * QueryPathOfRegTypeLib [OLEAUT32.164]
433 * Gets the path to a registered type library.
436 * guid [I] referenced guid
437 * wMaj [I] major version
438 * wMin [I] minor version
440 * path [O] path of typelib
444 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
445 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
448 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
452 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
457 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
460 /******************************************************************************
461 * CreateTypeLib [OLEAUT32.160] creates a typelib
467 HRESULT WINAPI
CreateTypeLib(
468 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
470 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
474 /******************************************************************************
475 * LoadTypeLib [OLEAUT32.161]
477 * Loads a type library
480 * szFile [I] Name of file to load from.
481 * pptLib [O] Pointer that receives ITypeLib object on success.
488 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
490 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
492 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
493 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
496 /******************************************************************************
497 * LoadTypeLibEx [OLEAUT32.183]
499 * Loads and optionally registers a type library
505 HRESULT WINAPI
LoadTypeLibEx(
506 LPCOLESTR szFile
, /* [in] Name of file to load from */
507 REGKIND regkind
, /* [in] Specify kind of registration */
508 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
510 WCHAR szPath
[MAX_PATH
+1];
513 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
517 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
522 case REGKIND_DEFAULT
:
523 /* don't register typelibs supplied with full path. Experimentation confirms the following */
524 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
525 (szFile
[0] && (szFile
[1] == ':'))) break;
526 /* else fall-through */
528 case REGKIND_REGISTER
:
529 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
531 ITypeLib_Release(*pptLib
);
539 TRACE(" returns %08x\n",res
);
543 /******************************************************************************
544 * LoadRegTypeLib [OLEAUT32.162]
546 * Loads a registered type library.
549 * rguid [I] GUID of the registered type library.
550 * wVerMajor [I] major version.
551 * wVerMinor [I] minor version.
552 * lcid [I] locale ID.
553 * ppTLib [O] pointer that receives an ITypeLib object on success.
557 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
560 HRESULT WINAPI
LoadRegTypeLib(
572 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
576 res
= LoadTypeLib(bstr
, ppTLib
);
583 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
584 if (res
== S_OK
&& (attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
))
586 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
587 ITypeLib_Release(*ppTLib
);
589 res
= TYPE_E_LIBNOTREGISTERED
;
594 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
600 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
601 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
602 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
603 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
604 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
605 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
607 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
612 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
613 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
614 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
616 get_interface_key( &tattr
->guid
, keyName
);
617 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
618 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
621 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
622 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
624 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
625 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
626 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
627 (const BYTE
*)PSOA
, sizeof PSOA
);
631 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
632 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
633 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
634 (const BYTE
*)PSOA
, sizeof PSOA
);
638 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
639 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
642 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
643 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
645 StringFromGUID2(&libattr
->guid
, buffer
, 40);
646 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
647 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
648 sprintfW(buffer
, fmtver
, libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
649 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
650 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
658 /******************************************************************************
659 * RegisterTypeLib [OLEAUT32.163]
660 * Adds information about a type library to the System Registry
662 * Docs: ITypeLib FAR * ptlib
663 * Docs: OLECHAR FAR* szFullPath
664 * Docs: OLECHAR FAR* szHelpDir
670 HRESULT WINAPI
RegisterTypeLib(
671 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
672 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
673 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
685 if (ptlib
== NULL
|| szFullPath
== NULL
)
688 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
692 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
695 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
698 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
699 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
703 /* Set the human-readable name of the typelib */
704 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
708 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
709 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
715 /* Make up the name of the typelib path subkey */
716 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
718 /* Create the typelib path subkey */
719 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
720 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
722 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
723 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
731 /* Create the flags subkey */
732 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
733 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
735 /* FIXME: is %u correct? */
736 static const WCHAR formatW
[] = {'%','u',0};
738 sprintfW(buf
, formatW
, attr
->wLibFlags
);
739 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
740 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
748 /* create the helpdir subkey */
749 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
750 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
752 BOOL freeHelpDir
= FALSE
;
755 /* if we created a new key, and helpDir was null, set the helpdir
756 to the directory which contains the typelib. However,
757 if we just opened an existing key, we leave the helpdir alone */
758 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
759 szHelpDir
= SysAllocString(szFullPath
);
760 pIndexStr
= strrchrW(szHelpDir
, '\\');
767 /* if we have an szHelpDir, set it! */
768 if (szHelpDir
!= NULL
) {
769 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
770 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
776 if (freeHelpDir
) SysFreeString(szHelpDir
);
788 /* register OLE Automation-compatible interfaces for this typelib */
789 types
= ITypeLib_GetTypeInfoCount(ptlib
);
790 for (tidx
=0; tidx
<types
; tidx
++) {
791 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
792 LPOLESTR name
= NULL
;
793 ITypeInfo
*tinfo
= NULL
;
795 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
798 case TKIND_INTERFACE
:
799 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
800 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
804 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
805 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
809 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
814 TYPEATTR
*tattr
= NULL
;
815 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
818 TRACE_(typelib
)("guid=%s, flags=%04x (",
819 debugstr_guid(&tattr
->guid
),
822 if (TRACE_ON(typelib
)) {
823 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
843 /* Register all dispinterfaces (which includes dual interfaces) and
844 oleautomation interfaces */
845 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
846 kind
== TKIND_DISPATCH
)
849 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
851 /* register interface<->typelib coupling */
852 TLB_register_interface(attr
, name
, tattr
, 0);
854 /* register TLBs into the opposite registry view, too */
855 if(opposite
== KEY_WOW64_32KEY
||
856 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
857 TLB_register_interface(attr
, name
, tattr
, opposite
);
860 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
863 ITypeInfo_Release(tinfo
);
870 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
876 /******************************************************************************
877 * UnRegisterTypeLib [OLEAUT32.186]
878 * Removes information about a type library from the System Registry
885 HRESULT WINAPI
UnRegisterTypeLib(
886 REFGUID libid
, /* [in] Guid of the library */
887 WORD wVerMajor
, /* [in] major version */
888 WORD wVerMinor
, /* [in] minor version */
889 LCID lcid
, /* [in] locale id */
892 BSTR tlibPath
= NULL
;
895 WCHAR subKeyName
[50];
898 BOOL deleteOtherStuff
;
901 TYPEATTR
* typeAttr
= NULL
;
903 ITypeInfo
* typeInfo
= NULL
;
904 ITypeLib
* typeLib
= NULL
;
907 TRACE("(IID: %s)\n",debugstr_guid(libid
));
909 /* Create the path to the key */
910 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
912 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
914 TRACE("Unsupported syskind %i\n", syskind
);
915 result
= E_INVALIDARG
;
919 /* get the path to the typelib on disk */
920 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
921 result
= E_INVALIDARG
;
925 /* Try and open the key to the type library. */
926 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
927 result
= E_INVALIDARG
;
931 /* Try and load the type library */
932 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
933 result
= TYPE_E_INVALIDSTATE
;
937 /* remove any types registered with this typelib */
938 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
939 for (i
=0; i
<numTypes
; i
++) {
940 /* get the kind of type */
941 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
945 /* skip non-interfaces, and get type info for the type */
946 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
949 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
952 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
956 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
957 kind
== TKIND_DISPATCH
)
959 /* the path to the type */
960 get_interface_key( &typeAttr
->guid
, subKeyName
);
962 /* Delete its bits */
963 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != ERROR_SUCCESS
)
966 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
967 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
968 RegDeleteKeyW(subKey
, TypeLibW
);
971 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
975 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
977 if (typeInfo
) ITypeInfo_Release(typeInfo
);
981 /* Now, delete the type library path subkey */
982 get_lcid_subkey( lcid
, syskind
, subKeyName
);
983 RegDeleteKeyW(key
, subKeyName
);
984 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
985 RegDeleteKeyW(key
, subKeyName
);
987 /* check if there is anything besides the FLAGS/HELPDIR keys.
988 If there is, we don't delete them */
989 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
990 deleteOtherStuff
= TRUE
;
992 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
993 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
995 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
996 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
997 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
998 deleteOtherStuff
= FALSE
;
1002 /* only delete the other parts of the key if we're absolutely sure */
1003 if (deleteOtherStuff
) {
1004 RegDeleteKeyW(key
, FLAGSW
);
1005 RegDeleteKeyW(key
, HELPDIRW
);
1009 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
1010 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
1011 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
1015 SysFreeString(tlibPath
);
1016 if (typeLib
) ITypeLib_Release(typeLib
);
1017 if (subKey
) RegCloseKey(subKey
);
1018 if (key
) RegCloseKey(key
);
1022 /******************************************************************************
1023 * RegisterTypeLibForUser [OLEAUT32.442]
1024 * Adds information about a type library to the user registry
1026 * Docs: ITypeLib FAR * ptlib
1027 * Docs: OLECHAR FAR* szFullPath
1028 * Docs: OLECHAR FAR* szHelpDir
1034 HRESULT WINAPI
RegisterTypeLibForUser(
1035 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
1036 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
1037 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1040 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1041 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1042 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1045 /******************************************************************************
1046 * UnRegisterTypeLibForUser [OLEAUT32.443]
1047 * Removes information about a type library from the user registry
1053 HRESULT WINAPI
UnRegisterTypeLibForUser(
1054 REFGUID libid
, /* [in] GUID of the library */
1055 WORD wVerMajor
, /* [in] major version */
1056 WORD wVerMinor
, /* [in] minor version */
1057 LCID lcid
, /* [in] locale id */
1060 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1061 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1062 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1065 /*======================= ITypeLib implementation =======================*/
1067 typedef struct tagTLBGuid
{
1074 typedef struct tagTLBCustData
1081 /* data structure for import typelibs */
1082 typedef struct tagTLBImpLib
1084 int offset
; /* offset in the file (MSFT)
1085 offset in nametable (SLTG)
1086 just used to identify library while reading
1088 TLBGuid
*guid
; /* libid */
1089 BSTR name
; /* name */
1091 LCID lcid
; /* lcid of imported typelib */
1093 WORD wVersionMajor
; /* major version number */
1094 WORD wVersionMinor
; /* minor version number */
1096 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1097 NULL if not yet loaded */
1101 typedef struct tagTLBString
{
1107 /* internal ITypeLib data */
1108 typedef struct tagITypeLibImpl
1110 ITypeLib2 ITypeLib2_iface
;
1111 ITypeComp ITypeComp_iface
;
1112 ICreateTypeLib2 ICreateTypeLib2_iface
;
1123 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1124 * exported to the application as a UNICODE string.
1126 struct list string_list
;
1127 struct list name_list
;
1128 struct list guid_list
;
1130 const TLBString
*Name
;
1131 const TLBString
*DocString
;
1132 const TLBString
*HelpFile
;
1133 const TLBString
*HelpStringDll
;
1134 DWORD dwHelpContext
;
1135 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1136 struct tagITypeInfoImpl
**typeinfos
;
1137 struct list custdata_list
;
1138 struct list implib_list
;
1139 int ctTypeDesc
; /* number of items in type desc array */
1140 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1141 library. Only used while reading MSFT
1143 struct list ref_list
; /* list of ref types in this typelib */
1144 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1147 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1153 static const ITypeLib2Vtbl tlbvt
;
1154 static const ITypeCompVtbl tlbtcvt
;
1155 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1157 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1159 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1162 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1164 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1167 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1169 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1172 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1174 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1177 /* ITypeLib methods */
1178 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1179 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1181 /*======================= ITypeInfo implementation =======================*/
1183 /* data for referenced types */
1184 typedef struct tagTLBRefType
1186 INT index
; /* Type index for internal ref or for external ref
1187 it the format is SLTG. -2 indicates to
1191 TLBGuid
*guid
; /* guid of the referenced type */
1192 /* if index == TLB_REF_USE_GUID */
1194 HREFTYPE reference
; /* The href of this ref */
1195 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1196 TLB_REF_INTERNAL for internal refs
1197 TLB_REF_NOT_FOUND for broken refs */
1202 #define TLB_REF_USE_GUID -2
1204 #define TLB_REF_INTERNAL (void*)-2
1205 #define TLB_REF_NOT_FOUND (void*)-1
1207 /* internal Parameter data */
1208 typedef struct tagTLBParDesc
1210 const TLBString
*Name
;
1211 struct list custdata_list
;
1214 /* internal Function data */
1215 typedef struct tagTLBFuncDesc
1217 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1218 const TLBString
*Name
; /* the name of this function */
1219 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1221 int HelpStringContext
;
1222 const TLBString
*HelpString
;
1223 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1224 struct list custdata_list
;
1227 /* internal Variable data */
1228 typedef struct tagTLBVarDesc
1230 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1231 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1232 const TLBString
*Name
; /* the name of this variable */
1234 int HelpStringContext
;
1235 const TLBString
*HelpString
;
1236 struct list custdata_list
;
1239 /* internal implemented interface data */
1240 typedef struct tagTLBImplType
1242 HREFTYPE hRef
; /* hRef of interface */
1243 int implflags
; /* IMPLFLAG_*s */
1244 struct list custdata_list
;
1247 /* internal TypeInfo data */
1248 typedef struct tagITypeInfoImpl
1250 ITypeInfo2 ITypeInfo2_iface
;
1251 ITypeComp ITypeComp_iface
;
1252 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1254 BOOL not_attached_to_typelib
;
1259 MEMBERID memidConstructor
;
1260 MEMBERID memidDestructor
;
1261 LPOLESTR lpstrSchema
;
1262 ULONG cbSizeInstance
;
1272 TYPEDESC
*tdescAlias
;
1273 IDLDESC idldescType
;
1275 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1276 int index
; /* index in this typelib; */
1277 HREFTYPE hreftype
; /* hreftype for app object binding */
1278 /* type libs seem to store the doc strings in ascii
1279 * so why should we do it in unicode?
1281 const TLBString
*Name
;
1282 const TLBString
*DocString
;
1283 const TLBString
*DllName
;
1284 const TLBString
*Schema
;
1285 DWORD dwHelpContext
;
1286 DWORD dwHelpStringContext
;
1289 TLBFuncDesc
*funcdescs
;
1292 TLBVarDesc
*vardescs
;
1294 /* Implemented Interfaces */
1295 TLBImplType
*impltypes
;
1297 struct list
*pcustdata_list
;
1298 struct list custdata_list
;
1301 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1303 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1306 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1308 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1311 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1313 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1316 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1318 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1321 static const ITypeInfo2Vtbl tinfvt
;
1322 static const ITypeCompVtbl tcompvt
;
1323 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1325 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1326 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1328 typedef struct tagTLBContext
1330 unsigned int oStart
; /* start of TLB in file */
1331 unsigned int pos
; /* current pos */
1332 unsigned int length
; /* total length */
1333 void *mapping
; /* memory mapping */
1334 MSFT_SegDir
* pTblDir
;
1335 ITypeLibImpl
* pLibInfo
;
1339 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1341 return str
!= NULL
? str
->str
: NULL
;
1344 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1348 return memcmp(left
, str
->str
, len
);
1351 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1353 return guid
!= NULL
? &guid
->guid
: NULL
;
1356 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1358 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1361 static int get_ptr_size(SYSKIND syskind
)
1371 WARN("Unhandled syskind: 0x%x\n", syskind
);
1378 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1379 if (pTD
->vt
& VT_RESERVED
)
1380 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1381 if (pTD
->vt
& VT_BYREF
)
1382 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1383 if (pTD
->vt
& VT_ARRAY
)
1384 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1385 if (pTD
->vt
& VT_VECTOR
)
1386 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1387 switch(pTD
->vt
& VT_TYPEMASK
) {
1388 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1389 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1390 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1391 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1392 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1393 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1394 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1395 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1396 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1397 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1398 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1399 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1400 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1401 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1402 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1403 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1404 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1405 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1406 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1407 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1408 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1409 pTD
->u
.hreftype
); break;
1410 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1411 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1412 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1413 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1415 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1416 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1418 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1419 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1420 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1423 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1427 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1429 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1430 dump_TypeDesc(&edesc
->tdesc
,buf
);
1431 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1432 MESSAGE("\t\tu.paramdesc.wParamFlags");
1433 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1434 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1435 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1436 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1437 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1438 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1439 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1440 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1441 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1443 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1445 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1446 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1447 MESSAGE("Param %d:\n",i
);
1448 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1450 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1451 switch (funcdesc
->funckind
) {
1452 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1453 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1454 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1455 case FUNC_STATIC
: MESSAGE("static");break;
1456 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1457 default: MESSAGE("unknown");break;
1459 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1460 switch (funcdesc
->invkind
) {
1461 case INVOKE_FUNC
: MESSAGE("func");break;
1462 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1463 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1464 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1466 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1467 switch (funcdesc
->callconv
) {
1468 case CC_CDECL
: MESSAGE("cdecl");break;
1469 case CC_PASCAL
: MESSAGE("pascal");break;
1470 case CC_STDCALL
: MESSAGE("stdcall");break;
1471 case CC_SYSCALL
: MESSAGE("syscall");break;
1474 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1475 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1476 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1478 MESSAGE("\telemdescFunc (return value type):\n");
1479 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1482 static const char * const typekind_desc
[] =
1495 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1498 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1499 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1500 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1503 dump_FUNCDESC(&(pfd
->funcdesc
));
1505 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1506 if(pfd
->Entry
== NULL
)
1507 MESSAGE("\tentry: (null)\n");
1508 else if(pfd
->Entry
== (void*)-1)
1509 MESSAGE("\tentry: invalid\n");
1510 else if(IS_INTRESOURCE(pfd
->Entry
))
1511 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1513 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1515 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1519 dump_TLBFuncDescOne(pfd
);
1524 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1528 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1534 static void dump_TLBImpLib(const TLBImpLib
*import
)
1536 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1537 debugstr_w(import
->name
));
1538 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1539 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1542 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1546 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1548 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1549 if(ref
->index
== -1)
1550 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1552 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1554 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1556 TRACE_(typelib
)("in lib\n");
1557 dump_TLBImpLib(ref
->pImpTLInfo
);
1562 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1567 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1568 impl
->hRef
, impl
->implflags
);
1574 static void dump_Variant(const VARIANT
* pvar
)
1578 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1582 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1583 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1585 TRACE(",%p", V_BYREF(pvar
));
1587 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1589 TRACE(",%p", V_ARRAY(pvar
));
1591 else switch (V_TYPE(pvar
))
1593 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1594 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1595 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1596 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1598 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1600 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1601 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1602 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1603 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1604 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1605 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1606 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1607 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1608 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1609 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1610 V_CY(pvar
).s
.Lo
); break;
1612 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1613 TRACE(",<invalid>");
1615 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1616 st
.wHour
, st
.wMinute
, st
.wSecond
);
1620 case VT_USERDEFINED
:
1622 case VT_NULL
: break;
1623 default: TRACE(",?"); break;
1629 static void dump_DispParms(const DISPPARAMS
* pdp
)
1633 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1635 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1637 TRACE("named args:\n");
1638 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1639 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1642 if (pdp
->cArgs
&& pdp
->rgvarg
)
1645 for (index
= 0; index
< pdp
->cArgs
; index
++)
1646 dump_Variant( &pdp
->rgvarg
[index
] );
1650 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1652 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1653 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1654 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1655 TRACE("kind:%s\n", typekind_desc
[pty
->typekind
]);
1656 TRACE("fct:%u var:%u impl:%u\n", pty
->cFuncs
, pty
->cVars
, pty
->cImplTypes
);
1657 TRACE("wTypeFlags: 0x%04x\n", pty
->wTypeFlags
);
1658 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1659 if (pty
->typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1661 dump_TLBFuncDesc(pty
->funcdescs
, pty
->cFuncs
);
1662 dump_TLBVarDesc(pty
->vardescs
, pty
->cVars
);
1663 dump_TLBImplType(pty
->impltypes
, pty
->cImplTypes
);
1666 static void dump_VARDESC(const VARDESC
*v
)
1668 MESSAGE("memid %d\n",v
->memid
);
1669 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1670 MESSAGE("oInst %d\n",v
->u
.oInst
);
1671 dump_ELEMDESC(&(v
->elemdescVar
));
1672 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1673 MESSAGE("varkind %d\n",v
->varkind
);
1676 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1678 /* VT_LPWSTR is largest type that, may appear in type description */
1679 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1680 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1681 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1682 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1683 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1684 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1685 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1686 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1689 static void TLB_abort(void)
1694 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1696 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1697 if (!ret
) ERR("cannot allocate memory\n");
1701 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1703 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1704 if (!ret
) ERR("cannot allocate memory\n");
1708 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1710 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1713 void heap_free(void *ptr
)
1715 HeapFree(GetProcessHeap(), 0, ptr
);
1718 /* returns the size required for a deep copy of a typedesc into a
1720 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1724 if (alloc_initial_space
)
1725 size
+= sizeof(TYPEDESC
);
1731 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1734 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1735 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1741 /* deep copy a typedesc into a flat buffer */
1742 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1747 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1756 dest
->u
.lptdesc
= buffer
;
1757 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1760 dest
->u
.lpadesc
= buffer
;
1761 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1762 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1763 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1769 /* free custom data allocated by MSFT_CustData */
1770 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1772 TLBCustData
*cd
, *cdn
;
1773 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1775 list_remove(&cd
->entry
);
1776 VariantClear(&cd
->data
);
1781 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1786 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1787 ret
= SysAllocStringLen(NULL
, len
- 1);
1788 if (!ret
) return ret
;
1789 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1793 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1794 UINT n
, MEMBERID memid
)
1797 if(funcdescs
->funcdesc
.memid
== memid
)
1805 static inline TLBFuncDesc
*TLB_get_funcdesc_by_name(TLBFuncDesc
*funcdescs
,
1806 UINT n
, const OLECHAR
*name
)
1809 if(!lstrcmpiW(TLB_get_bstr(funcdescs
->Name
), name
))
1817 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1818 UINT n
, MEMBERID memid
)
1821 if(vardescs
->vardesc
.memid
== memid
)
1829 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1830 UINT n
, const OLECHAR
*name
)
1833 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1841 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1843 TLBCustData
*cust_data
;
1844 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1845 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1850 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1851 UINT n
, const OLECHAR
*name
)
1854 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1862 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1864 list_init(&var_desc
->custdata_list
);
1867 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1871 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1876 TLBVarDesc_Constructor(&ret
[n
-1]);
1883 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1887 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1892 list_init(&ret
[n
-1].custdata_list
);
1899 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1901 list_init(&func_desc
->custdata_list
);
1904 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1908 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1913 TLBFuncDesc_Constructor(&ret
[n
-1]);
1920 static void TLBImplType_Constructor(TLBImplType
*impl
)
1922 list_init(&impl
->custdata_list
);
1925 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1929 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1934 TLBImplType_Constructor(&ret
[n
-1]);
1941 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1942 const GUID
*new_guid
, HREFTYPE hreftype
)
1946 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1947 if (IsEqualGUID(&guid
->guid
, new_guid
))
1951 guid
= heap_alloc(sizeof(TLBGuid
));
1955 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1956 guid
->hreftype
= hreftype
;
1958 list_add_tail(guid_list
, &guid
->entry
);
1963 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1965 TLBCustData
*cust_data
;
1977 return DISP_E_BADVARTYPE
;
1980 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1983 cust_data
= heap_alloc(sizeof(TLBCustData
));
1985 return E_OUTOFMEMORY
;
1987 cust_data
->guid
= tlbguid
;
1988 VariantInit(&cust_data
->data
);
1990 list_add_tail(custdata_list
, &cust_data
->entry
);
1992 VariantClear(&cust_data
->data
);
1994 return VariantCopy(&cust_data
->data
, var
);
1997 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
2004 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
2005 if (strcmpW(str
->str
, new_str
) == 0)
2009 str
= heap_alloc(sizeof(TLBString
));
2013 str
->str
= SysAllocString(new_str
);
2019 list_add_tail(string_list
, &str
->entry
);
2024 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
2025 ULONG
*size
, WORD
*align
)
2031 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
2035 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
2037 ITypeInfo_Release(other
);
2042 *size
= attr
->cbSizeInstance
;
2044 *align
= attr
->cbAlignment
;
2046 ITypeInfo_ReleaseTypeAttr(other
, attr
);
2047 ITypeInfo_Release(other
);
2052 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
2053 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
2055 ULONG i
, sub
, ptr_size
;
2058 ptr_size
= get_ptr_size(sys
);
2097 *size
= sizeof(DATE
);
2100 *size
= sizeof(VARIANT
);
2102 if(sys
== SYS_WIN32
)
2103 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2107 *size
= sizeof(DECIMAL
);
2114 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2115 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2116 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2121 case VT_USERDEFINED
:
2122 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2124 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2138 /**********************************************************************
2140 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2142 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
2147 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2149 if (where
!= DO_NOT_SEEK
)
2151 where
+= pcx
->oStart
;
2152 if (where
> pcx
->length
)
2155 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2163 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2165 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2166 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2168 MSFT_Seek(pcx
, where
);
2169 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2170 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2175 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2180 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2181 FromLEDWords(buffer
, ret
);
2186 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2191 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2192 FromLEWords(buffer
, ret
);
2197 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2200 MSFT_GuidEntry entry
;
2203 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2205 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2208 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2210 guid
= heap_alloc(sizeof(TLBGuid
));
2212 guid
->offset
= offs
;
2213 guid
->guid
= entry
.guid
;
2214 guid
->hreftype
= entry
.hreftype
;
2216 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2218 offs
+= sizeof(MSFT_GuidEntry
);
2222 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2226 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2227 if(ret
->offset
== offset
){
2228 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2236 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2238 MSFT_NameIntro niName
;
2242 ERR_(typelib
)("bad offset %d\n", offset
);
2246 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2247 pcx
->pTblDir
->pNametab
.offset
+offset
);
2249 return niName
.hreftype
;
2252 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2255 MSFT_NameIntro intro
;
2257 int offs
= 0, lengthInChars
;
2259 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2263 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2266 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2267 intro
.namelen
&= 0xFF;
2268 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2270 len_piece
= (len_piece
+ 4) & ~0x3;
2274 string
= heap_alloc(len_piece
+ 1);
2275 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2276 string
[intro
.namelen
] = '\0';
2278 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2279 string
, -1, NULL
, 0);
2280 if (!lengthInChars
) {
2282 return E_UNEXPECTED
;
2285 tlbstr
= heap_alloc(sizeof(TLBString
));
2287 tlbstr
->offset
= offs
;
2288 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2289 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2293 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2299 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2303 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2304 if (tlbstr
->offset
== offset
) {
2305 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2313 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2317 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2318 if (tlbstr
->offset
== offset
) {
2319 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2328 * read a value and fill a VARIANT structure
2330 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2334 TRACE_(typelib
)("\n");
2336 if(offset
<0) { /* data are packed in here */
2337 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2338 V_I4(pVar
) = offset
& 0x3ffffff;
2341 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2342 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2343 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2344 switch (V_VT(pVar
)){
2345 case VT_EMPTY
: /* FIXME: is this right? */
2346 case VT_NULL
: /* FIXME: is this right? */
2347 case VT_I2
: /* this should not happen */
2358 case VT_VOID
: /* FIXME: is this right? */
2366 case VT_DECIMAL
: /* FIXME: is this right? */
2369 /* pointer types with known behaviour */
2372 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2374 V_BSTR(pVar
) = NULL
;
2376 ptr
= heap_alloc_zero(size
);
2377 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2378 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2379 /* FIXME: do we need a AtoW conversion here? */
2380 V_UNION(pVar
, bstrVal
[size
])='\0';
2381 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2386 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2393 case VT_USERDEFINED
:
2399 case VT_STREAMED_OBJECT
:
2400 case VT_STORED_OBJECT
:
2401 case VT_BLOB_OBJECT
:
2406 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2410 if(size
>0) /* (big|small) endian correct? */
2411 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2415 * create a linked list with custom data
2417 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2423 TRACE_(typelib
)("\n");
2425 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2429 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2430 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2431 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2432 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2433 list_add_head(custdata_list
, &pNew
->entry
);
2434 offset
= entry
.next
;
2439 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2442 pTd
->vt
=type
& VT_TYPEMASK
;
2444 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2446 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2449 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2451 return (invkind
== INVOKE_PROPERTYGET
||
2452 invkind
== INVOKE_PROPERTYPUT
||
2453 invkind
== INVOKE_PROPERTYPUTREF
);
2457 MSFT_DoFuncs(TLBContext
* pcx
,
2462 TLBFuncDesc
** pptfd
)
2465 * member information is stored in a data structure at offset
2466 * indicated by the memoffset field of the typeinfo structure
2467 * There are several distinctive parts.
2468 * The first part starts with a field that holds the total length
2469 * of this (first) part excluding this field. Then follow the records,
2470 * for each member there is one record.
2472 * The first entry is always the length of the record (including this
2474 * The rest of the record depends on the type of the member. If there is
2475 * a field indicating the member type (function, variable, interface, etc)
2476 * I have not found it yet. At this time we depend on the information
2477 * in the type info and the usual order how things are stored.
2479 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2482 * Third is an equal sized array with file offsets to the name entry
2485 * The fourth and last (?) part is an array with offsets to the records
2486 * in the first part of this file segment.
2489 int infolen
, nameoffset
, reclength
, i
;
2490 int recoffset
= offset
+ sizeof(INT
);
2492 char *recbuf
= heap_alloc(0xffff);
2493 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2494 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2496 TRACE_(typelib
)("\n");
2498 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2500 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2502 for ( i
= 0; i
< cFuncs
; i
++ )
2506 /* name, eventually add to a hash table */
2507 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2508 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2510 /* read the function information record */
2511 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2513 reclength
&= 0xffff;
2515 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2517 /* size without argument data */
2518 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2519 if (pFuncRec
->FKCCIC
& 0x1000)
2520 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2522 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2523 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2525 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2526 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2528 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2530 if (pFuncRec
->FKCCIC
& 0x2000 )
2532 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2533 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2534 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2537 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2540 ptfd
->Entry
= (TLBString
*)-1;
2542 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2543 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2545 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2546 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2548 /* fill the FuncDesc Structure */
2549 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2550 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2552 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2553 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2554 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2555 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2556 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2557 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2558 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2560 /* nameoffset is sometimes -1 on the second half of a propget/propput
2561 * pair of functions */
2562 if ((nameoffset
== -1) && (i
> 0) &&
2563 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2564 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2565 ptfd
->Name
= ptfd_prev
->Name
;
2567 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2571 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2573 /* do the parameters/arguments */
2574 if(pFuncRec
->nrargs
)
2577 MSFT_ParameterInfo paraminfo
;
2579 ptfd
->funcdesc
.lprgelemdescParam
=
2580 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2582 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2584 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2585 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2587 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2589 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2595 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2598 if (paraminfo
.oName
!= -1)
2599 ptfd
->pParamDesc
[j
].Name
=
2600 MSFT_ReadName( pcx
, paraminfo
.oName
);
2601 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2604 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2605 (pFuncRec
->FKCCIC
& 0x1000) )
2607 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2609 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2611 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2613 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2614 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2616 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2620 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2623 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2624 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2625 pFuncRec
->FKCCIC
& 0x80 )
2628 pFuncRec
->oArgCustData
[j
],
2629 &ptfd
->pParamDesc
[j
].custdata_list
);
2632 /* SEEK value = jump to offset,
2633 * from there jump to the end of record,
2634 * go back by (j-1) arguments
2636 MSFT_ReadLEDWords( ¶minfo
,
2637 sizeof(MSFT_ParameterInfo
), pcx
,
2638 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2639 * sizeof(MSFT_ParameterInfo
)));
2643 /* scode is not used: archaic win16 stuff FIXME: right? */
2644 ptfd
->funcdesc
.cScodes
= 0 ;
2645 ptfd
->funcdesc
.lprgscode
= NULL
;
2649 recoffset
+= reclength
;
2654 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2655 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2657 int infolen
, nameoffset
, reclength
;
2659 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2664 TRACE_(typelib
)("\n");
2666 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2667 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2668 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2669 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2670 recoffset
+= offset
+sizeof(INT
);
2671 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2672 /* name, eventually add to a hash table */
2673 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2674 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2675 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2676 /* read the variable information record */
2677 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2679 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2682 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2683 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2685 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2686 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2688 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2689 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2691 /* fill the VarDesc Structure */
2692 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2693 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2694 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2695 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2696 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2697 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2698 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2699 if(pVarRec
->VarKind
== VAR_CONST
){
2700 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2701 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2702 pVarRec
->OffsValue
, pcx
);
2704 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2705 recoffset
+= reclength
;
2709 /* process Implemented Interfaces of a com class */
2710 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2714 MSFT_RefRecord refrec
;
2717 TRACE_(typelib
)("\n");
2719 pTI
->impltypes
= TLBImplType_Alloc(count
);
2720 pImpl
= pTI
->impltypes
;
2721 for(i
=0;i
<count
;i
++){
2722 if(offset
<0) break; /* paranoia */
2723 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2724 pImpl
->hRef
= refrec
.reftype
;
2725 pImpl
->implflags
=refrec
.flags
;
2726 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2727 offset
=refrec
.onext
;
2733 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2734 * and some structures, and fix the alignment */
2735 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2737 if(info
->typekind
== TKIND_ALIAS
){
2738 switch(info
->tdescAlias
->vt
){
2746 info
->cbSizeInstance
= sizeof(void*);
2747 info
->cbAlignment
= sizeof(void*);
2750 case VT_USERDEFINED
:
2751 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->cbSizeInstance
, &info
->cbAlignment
);
2754 info
->cbSizeInstance
= sizeof(VARIANT
);
2755 info
->cbAlignment
= 8;
2757 if(info
->cbSizeInstance
< sizeof(void*))
2758 info
->cbAlignment
= info
->cbSizeInstance
;
2760 info
->cbAlignment
= sizeof(void*);
2763 }else if(info
->typekind
== TKIND_INTERFACE
||
2764 info
->typekind
== TKIND_DISPATCH
||
2765 info
->typekind
== TKIND_COCLASS
){
2766 info
->cbSizeInstance
= sizeof(void*);
2767 info
->cbAlignment
= sizeof(void*);
2773 * process a typeinfo record
2775 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2778 ITypeLibImpl
* pLibInfo
)
2780 MSFT_TypeInfoBase tiBase
;
2781 ITypeInfoImpl
*ptiRet
;
2783 TRACE_(typelib
)("count=%u\n", count
);
2785 ptiRet
= ITypeInfoImpl_Constructor();
2786 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2787 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2789 /* this is where we are coming from */
2790 ptiRet
->pTypeLib
= pLibInfo
;
2791 ptiRet
->index
=count
;
2793 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2794 ptiRet
->lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2795 ptiRet
->lpstrSchema
=NULL
; /* reserved */
2796 ptiRet
->cbSizeInstance
=tiBase
.size
;
2797 ptiRet
->typekind
=tiBase
.typekind
& 0xF;
2798 ptiRet
->cFuncs
=LOWORD(tiBase
.cElement
);
2799 ptiRet
->cVars
=HIWORD(tiBase
.cElement
);
2800 ptiRet
->cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2801 ptiRet
->wTypeFlags
=tiBase
.flags
;
2802 ptiRet
->wMajorVerNum
=LOWORD(tiBase
.version
);
2803 ptiRet
->wMinorVerNum
=HIWORD(tiBase
.version
);
2804 ptiRet
->cImplTypes
=tiBase
.cImplTypes
;
2805 ptiRet
->cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2806 if(ptiRet
->typekind
== TKIND_ALIAS
){
2808 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2809 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2810 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2814 /* IDLDESC idldescType; *//* never saw this one != zero */
2816 /* name, eventually add to a hash table */
2817 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2818 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2819 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2821 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2822 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2823 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2825 if (ptiRet
->typekind
== TKIND_MODULE
)
2826 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2828 /* note: InfoType's Help file and HelpStringDll come from the containing
2829 * library. Further HelpString and Docstring appear to be the same thing :(
2832 if(ptiRet
->cFuncs
>0 )
2833 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->cFuncs
,
2835 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2837 if(ptiRet
->cVars
>0 )
2838 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->cFuncs
,
2840 tiBase
.memoffset
, &ptiRet
->vardescs
);
2841 if(ptiRet
->cImplTypes
>0 ) {
2842 switch(ptiRet
->typekind
)
2845 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->cImplTypes
,
2848 case TKIND_DISPATCH
:
2849 /* This is not -1 when the interface is a non-base dual interface or
2850 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2851 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2855 if (tiBase
.datatype1
!= -1)
2857 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2858 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2862 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2863 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2867 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2869 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2870 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2871 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2872 typekind_desc
[ptiRet
->typekind
]);
2873 if (TRACE_ON(typelib
))
2874 dump_TypeInfo(ptiRet
);
2879 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2882 INT16 len_str
, len_piece
;
2883 int offs
= 0, lengthInChars
;
2885 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2889 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2892 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2893 len_piece
= len_str
+ sizeof(INT16
);
2895 len_piece
= (len_piece
+ 4) & ~0x3;
2899 string
= heap_alloc(len_piece
+ 1);
2900 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2901 string
[len_str
] = '\0';
2903 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2904 string
, -1, NULL
, 0);
2905 if (!lengthInChars
) {
2907 return E_UNEXPECTED
;
2910 tlbstr
= heap_alloc(sizeof(TLBString
));
2912 tlbstr
->offset
= offs
;
2913 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2914 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2918 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2924 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2929 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2930 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2931 MSFT_ImpInfo impinfo
;
2934 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2936 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2937 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2939 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2940 if(pImpLib
->offset
==impinfo
.oImpFile
)
2943 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2944 ref
->reference
= offs
;
2945 ref
->pImpTLInfo
= pImpLib
;
2946 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2947 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2948 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2949 ref
->index
= TLB_REF_USE_GUID
;
2951 ref
->index
= impinfo
.oGuid
;
2953 ERR("Cannot find a reference\n");
2954 ref
->reference
= -1;
2955 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2958 offs
+= sizeof(impinfo
);
2964 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2965 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2966 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2969 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2970 static CRITICAL_SECTION cache_section
;
2971 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2973 0, 0, &cache_section
,
2974 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2975 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2977 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2980 typedef struct TLB_PEFile
2982 IUnknown IUnknown_iface
;
2985 HRSRC typelib_resource
;
2986 HGLOBAL typelib_global
;
2987 LPVOID typelib_base
;
2990 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2992 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2995 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2997 if (IsEqualIID(riid
, &IID_IUnknown
))
3000 IUnknown_AddRef(iface
);
3004 return E_NOINTERFACE
;
3007 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
3009 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
3010 return InterlockedIncrement(&This
->refs
);
3013 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
3015 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
3016 ULONG refs
= InterlockedDecrement(&This
->refs
);
3019 if (This
->typelib_global
)
3020 FreeResource(This
->typelib_global
);
3022 FreeLibrary(This
->dll
);
3028 static const IUnknownVtbl TLB_PEFile_Vtable
=
3030 TLB_PEFile_QueryInterface
,
3035 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3038 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3040 This
= heap_alloc(sizeof(TLB_PEFile
));
3042 return E_OUTOFMEMORY
;
3044 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
3047 This
->typelib_resource
= NULL
;
3048 This
->typelib_global
= NULL
;
3049 This
->typelib_base
= NULL
;
3051 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
3052 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
3056 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
3057 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
3058 if (This
->typelib_resource
)
3060 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
3061 if (This
->typelib_global
)
3063 This
->typelib_base
= LockResource(This
->typelib_global
);
3065 if (This
->typelib_base
)
3067 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
3068 *ppBase
= This
->typelib_base
;
3069 *ppFile
= &This
->IUnknown_iface
;
3075 TRACE("No TYPELIB resource found\n");
3079 TLB_PEFile_Release(&This
->IUnknown_iface
);
3083 typedef struct TLB_NEFile
3085 IUnknown IUnknown_iface
;
3087 LPVOID typelib_base
;
3090 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
3092 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
3095 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3097 if (IsEqualIID(riid
, &IID_IUnknown
))
3100 IUnknown_AddRef(iface
);
3104 return E_NOINTERFACE
;
3107 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
3109 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3110 return InterlockedIncrement(&This
->refs
);
3113 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
3115 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3116 ULONG refs
= InterlockedDecrement(&This
->refs
);
3119 heap_free(This
->typelib_base
);
3125 static const IUnknownVtbl TLB_NEFile_Vtable
=
3127 TLB_NEFile_QueryInterface
,
3132 /***********************************************************************
3133 * read_xx_header [internal]
3135 static int read_xx_header( HFILE lzfd
)
3137 IMAGE_DOS_HEADER mzh
;
3140 LZSeek( lzfd
, 0, SEEK_SET
);
3141 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3143 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3146 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3147 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3150 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3152 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3153 return IMAGE_OS2_SIGNATURE
;
3154 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3155 return IMAGE_NT_SIGNATURE
;
3158 WARN("Can't handle %s files.\n", magic
);
3163 /***********************************************************************
3164 * find_ne_resource [internal]
3166 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3167 DWORD
*resLen
, DWORD
*resOff
)
3169 IMAGE_OS2_HEADER nehd
;
3170 NE_TYPEINFO
*typeInfo
;
3171 NE_NAMEINFO
*nameInfo
;
3177 /* Read in NE header */
3178 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3179 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3181 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3184 TRACE("No resources in NE dll\n" );
3188 /* Read in resource table */
3189 resTab
= heap_alloc( resTabSize
);
3190 if ( !resTab
) return FALSE
;
3192 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3193 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3195 heap_free( resTab
);
3200 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3202 if (!IS_INTRESOURCE(typeid)) /* named type */
3204 BYTE len
= strlen( typeid );
3205 while (typeInfo
->type_id
)
3207 if (!(typeInfo
->type_id
& 0x8000))
3209 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3210 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
3212 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3213 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3216 else /* numeric type id */
3218 WORD id
= LOWORD(typeid) | 0x8000;
3219 while (typeInfo
->type_id
)
3221 if (typeInfo
->type_id
== id
) goto found_type
;
3222 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3223 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3226 TRACE("No typeid entry found for %p\n", typeid );
3227 heap_free( resTab
);
3231 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3233 if (!IS_INTRESOURCE(resid
)) /* named resource */
3235 BYTE len
= strlen( resid
);
3236 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3238 BYTE
*p
= resTab
+ nameInfo
->id
;
3239 if (nameInfo
->id
& 0x8000) continue;
3240 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3243 else /* numeric resource id */
3245 WORD id
= LOWORD(resid
) | 0x8000;
3246 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3247 if (nameInfo
->id
== id
) goto found_name
;
3249 TRACE("No resid entry found for %p\n", typeid );
3250 heap_free( resTab
);
3254 /* Return resource data */
3255 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3256 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3258 heap_free( resTab
);
3262 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3266 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3269 This
= heap_alloc(sizeof(TLB_NEFile
));
3270 if (!This
) return E_OUTOFMEMORY
;
3272 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3274 This
->typelib_base
= NULL
;
3276 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3277 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3279 DWORD reslen
, offset
;
3280 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3282 This
->typelib_base
= heap_alloc(reslen
);
3283 if( !This
->typelib_base
)
3287 LZSeek( lzfd
, offset
, SEEK_SET
);
3288 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3290 *ppBase
= This
->typelib_base
;
3291 *pdwTLBLength
= reslen
;
3292 *ppFile
= &This
->IUnknown_iface
;
3298 if( lzfd
>= 0) LZClose( lzfd
);
3299 TLB_NEFile_Release(&This
->IUnknown_iface
);
3303 typedef struct TLB_Mapping
3305 IUnknown IUnknown_iface
;
3309 LPVOID typelib_base
;
3312 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3314 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3317 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3319 if (IsEqualIID(riid
, &IID_IUnknown
))
3322 IUnknown_AddRef(iface
);
3326 return E_NOINTERFACE
;
3329 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3331 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3332 return InterlockedIncrement(&This
->refs
);
3335 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3337 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3338 ULONG refs
= InterlockedDecrement(&This
->refs
);
3341 if (This
->typelib_base
)
3342 UnmapViewOfFile(This
->typelib_base
);
3344 CloseHandle(This
->mapping
);
3345 if (This
->file
!= INVALID_HANDLE_VALUE
)
3346 CloseHandle(This
->file
);
3352 static const IUnknownVtbl TLB_Mapping_Vtable
=
3354 TLB_Mapping_QueryInterface
,
3359 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3363 This
= heap_alloc(sizeof(TLB_Mapping
));
3365 return E_OUTOFMEMORY
;
3367 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3369 This
->file
= INVALID_HANDLE_VALUE
;
3370 This
->mapping
= NULL
;
3371 This
->typelib_base
= NULL
;
3373 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3374 if (INVALID_HANDLE_VALUE
!= This
->file
)
3376 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3379 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3380 if(This
->typelib_base
)
3382 /* retrieve file size */
3383 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3384 *ppBase
= This
->typelib_base
;
3385 *ppFile
= &This
->IUnknown_iface
;
3391 IUnknown_Release(&This
->IUnknown_iface
);
3392 return TYPE_E_CANTLOADLIBRARY
;
3395 /****************************************************************************
3398 * find the type of the typelib file and map the typelib resource into
3402 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3403 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3405 ITypeLibImpl
*entry
;
3408 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3409 LPVOID pBase
= NULL
;
3410 DWORD dwTLBLength
= 0;
3411 IUnknown
*pFile
= NULL
;
3416 index_str
= strrchrW(pszFileName
, '\\');
3417 if(index_str
&& *++index_str
!= '\0')
3420 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3421 if(*end_ptr
== '\0')
3423 int str_len
= index_str
- pszFileName
- 1;
3425 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3426 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3431 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3433 if(strchrW(file
, '\\'))
3435 lstrcpyW(pszPath
, file
);
3439 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3440 pszPath
[len
] = '\\';
3441 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3445 if(file
!= pszFileName
) heap_free(file
);
3447 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3448 if(h
!= INVALID_HANDLE_VALUE
){
3449 FILE_NAME_INFORMATION
*info
;
3450 char data
[MAX_PATH
* sizeof(WCHAR
) + sizeof(info
->FileNameLength
)];
3453 info
= (FILE_NAME_INFORMATION
*)data
;
3454 /* GetFileInformationByHandleEx returns the path of the file without
3455 * WOW64 redirection */
3456 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, data
, sizeof(data
));
3458 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3459 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3464 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3466 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3467 EnterCriticalSection(&cache_section
);
3468 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3470 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3472 TRACE("cache hit\n");
3473 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3474 ITypeLib2_AddRef(*ppTypeLib
);
3475 LeaveCriticalSection(&cache_section
);
3479 LeaveCriticalSection(&cache_section
);
3481 /* now actually load and parse the typelib */
3483 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3484 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3485 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3486 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3487 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3490 if (dwTLBLength
>= 4)
3492 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3493 if (dwSignature
== MSFT_SIGNATURE
)
3494 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3495 else if (dwSignature
== SLTG_SIGNATURE
)
3496 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3499 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3500 ret
= TYPE_E_CANTLOADLIBRARY
;
3504 ret
= TYPE_E_CANTLOADLIBRARY
;
3505 IUnknown_Release(pFile
);
3509 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3511 TRACE("adding to cache\n");
3512 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3513 lstrcpyW(impl
->path
, pszPath
);
3514 /* We should really canonicalise the path here. */
3515 impl
->index
= index
;
3517 /* FIXME: check if it has added already in the meantime */
3518 EnterCriticalSection(&cache_section
);
3519 list_add_head(&tlb_cache
, &impl
->entry
);
3520 LeaveCriticalSection(&cache_section
);
3526 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3528 ret
= TYPE_E_CANTLOADLIBRARY
;
3535 /*================== ITypeLib(2) Methods ===================================*/
3537 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3539 ITypeLibImpl
* pTypeLibImpl
;
3541 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3542 if (!pTypeLibImpl
) return NULL
;
3544 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3545 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3546 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3547 pTypeLibImpl
->ref
= 1;
3549 list_init(&pTypeLibImpl
->implib_list
);
3550 list_init(&pTypeLibImpl
->custdata_list
);
3551 list_init(&pTypeLibImpl
->name_list
);
3552 list_init(&pTypeLibImpl
->string_list
);
3553 list_init(&pTypeLibImpl
->guid_list
);
3554 list_init(&pTypeLibImpl
->ref_list
);
3555 pTypeLibImpl
->dispatch_href
= -1;
3557 return pTypeLibImpl
;
3560 /****************************************************************************
3561 * ITypeLib2_Constructor_MSFT
3563 * loading an MSFT typelib from an in-memory image
3565 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3569 MSFT_Header tlbHeader
;
3570 MSFT_SegDir tlbSegDir
;
3571 ITypeLibImpl
* pTypeLibImpl
;
3574 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3576 pTypeLibImpl
= TypeLibImpl_Constructor();
3577 if (!pTypeLibImpl
) return NULL
;
3579 /* get pointer to beginning of typelib data */
3583 cx
.pLibInfo
= pTypeLibImpl
;
3584 cx
.length
= dwTLBLength
;
3587 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3588 TRACE_(typelib
)("header:\n");
3589 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3590 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3591 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3594 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3596 /* there is a small amount of information here until the next important
3598 * the segment directory . Try to calculate the amount of data */
3599 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3601 /* now read the segment directory */
3602 TRACE("read segment directory (at %d)\n",lPSegDir
);
3603 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3604 cx
.pTblDir
= &tlbSegDir
;
3606 /* just check two entries */
3607 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3609 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3610 heap_free(pTypeLibImpl
);
3614 MSFT_ReadAllNames(&cx
);
3615 MSFT_ReadAllStrings(&cx
);
3616 MSFT_ReadAllGuids(&cx
);
3618 /* now fill our internal data */
3619 /* TLIBATTR fields */
3620 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3622 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3623 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3624 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3625 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3626 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3628 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3629 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3631 /* name, eventually add to a hash table */
3632 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3635 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3636 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3638 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3641 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3642 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3645 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3648 if(tlbHeader
.CustomDataOffset
>= 0)
3650 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3653 /* fill in type descriptions */
3654 if(tlbSegDir
.pTypdescTab
.length
> 0)
3656 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3658 pTypeLibImpl
->ctTypeDesc
= cTD
;
3659 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3660 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3663 /* FIXME: add several sanity checks here */
3664 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3665 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3667 /* FIXME: check safearray */
3669 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3671 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3673 else if(td
[0] == VT_CARRAY
)
3675 /* array descr table here */
3676 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3678 else if(td
[0] == VT_USERDEFINED
)
3680 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3682 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3685 /* second time around to fill the array subscript info */
3688 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3689 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3691 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3692 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3695 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3697 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3699 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3701 for(j
= 0; j
<td
[2]; j
++)
3703 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3704 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3705 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3706 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3711 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3712 ERR("didn't find array description data\n");
3717 /* imported type libs */
3718 if(tlbSegDir
.pImpFiles
.offset
>0)
3721 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3724 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3728 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3729 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3730 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3732 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3733 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3734 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3735 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3738 name
= heap_alloc_zero(size
+1);
3739 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3740 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3743 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3744 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3746 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3750 MSFT_ReadAllRefs(&cx
);
3752 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3755 if(tlbHeader
.nrtypeinfos
>= 0 )
3757 ITypeInfoImpl
**ppTI
;
3759 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3761 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3763 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3766 (pTypeLibImpl
->TypeInfoCount
)++;
3771 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3772 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3773 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3777 TRACE("(%p)\n", pTypeLibImpl
);
3778 return &pTypeLibImpl
->ITypeLib2_iface
;
3782 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3788 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3789 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3793 guid
->Data4
[0] = s
>> 8;
3794 guid
->Data4
[1] = s
& 0xff;
3797 for(i
= 0; i
< 6; i
++) {
3798 memcpy(b
, str
+ 24 + 2 * i
, 2);
3799 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3804 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3811 bytelen
= *(const WORD
*)ptr
;
3812 if(bytelen
== 0xffff) return 2;
3814 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3815 tmp_str
= SysAllocStringLen(NULL
, len
);
3817 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3818 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3819 SysFreeString(tmp_str
);
3824 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3829 bytelen
= *(const WORD
*)ptr
;
3830 if(bytelen
== 0xffff) return 2;
3831 *str
= heap_alloc(bytelen
+ 1);
3832 memcpy(*str
, ptr
+ 2, bytelen
);
3833 (*str
)[bytelen
] = '\0';
3837 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3842 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3843 if (tlbstr
->offset
== offset
)
3847 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3848 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3849 SysFreeString(tmp_str
);
3854 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3856 char *ptr
= pLibBlk
;
3859 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3860 FIXME("libblk magic = %04x\n", w
);
3865 if((w
= *(WORD
*)ptr
) != 0xffff) {
3866 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3871 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3873 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3875 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3878 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3879 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3882 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3883 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3885 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3888 ptr
+= 4; /* skip res12 */
3890 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3893 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3896 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3899 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3900 ptr
+= sizeof(GUID
);
3902 return ptr
- (char*)pLibBlk
;
3905 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3910 } sltg_ref_lookup_t
;
3912 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3913 HREFTYPE
*typelib_ref
)
3915 if(table
&& typeinfo_ref
< table
->num
)
3917 *typelib_ref
= table
->refs
[typeinfo_ref
];
3921 ERR_(typelib
)("Unable to find reference\n");
3926 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3931 if((*pType
& 0xe00) == 0xe00) {
3933 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3934 pTD
= pTD
->u
.lptdesc
;
3936 switch(*pType
& 0x3f) {
3939 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3940 pTD
= pTD
->u
.lptdesc
;
3943 case VT_USERDEFINED
:
3944 pTD
->vt
= VT_USERDEFINED
;
3945 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3951 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3954 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3956 pTD
->vt
= VT_CARRAY
;
3957 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3958 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3959 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3960 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3962 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3968 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3972 pTD
->vt
= VT_SAFEARRAY
;
3973 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3974 pTD
= pTD
->u
.lptdesc
;
3978 pTD
->vt
= *pType
& 0x3f;
3987 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3988 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3990 /* Handle [in/out] first */
3991 if((*pType
& 0xc000) == 0xc000)
3992 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3993 else if(*pType
& 0x8000)
3994 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3995 else if(*pType
& 0x4000)
3996 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3998 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
4001 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
4004 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
4006 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
4010 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
4015 TLBRefType
*ref_type
;
4016 sltg_ref_lookup_t
*table
;
4017 HREFTYPE typelib_ref
;
4019 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
4020 FIXME("Ref magic = %x\n", pRef
->magic
);
4023 name
= ( (char*)pRef
->names
+ pRef
->number
);
4025 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
4026 table
->num
= pRef
->number
>> 3;
4028 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
4030 /* We don't want the first href to be 0 */
4031 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
4033 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
4035 unsigned int lib_offs
, type_num
;
4037 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
4039 name
+= SLTG_ReadStringA(name
, &refname
);
4040 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
4041 FIXME_(typelib
)("Can't sscanf ref\n");
4042 if(lib_offs
!= 0xffff) {
4045 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
4046 if(import
->offset
== lib_offs
)
4049 if(&import
->entry
== &pTL
->implib_list
) {
4050 char fname
[MAX_PATH
+1];
4054 import
= heap_alloc_zero(sizeof(*import
));
4055 import
->offset
= lib_offs
;
4056 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
4057 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
4058 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
4059 &import
->wVersionMajor
,
4060 &import
->wVersionMinor
,
4061 &import
->lcid
, fname
) != 4) {
4062 FIXME_(typelib
)("can't sscanf ref %s\n",
4063 pNameTable
+ lib_offs
+ 40);
4065 len
= strlen(fname
);
4066 if(fname
[len
-1] != '#')
4067 FIXME("fname = %s\n", fname
);
4068 fname
[len
-1] = '\0';
4069 import
->name
= TLB_MultiByteToBSTR(fname
);
4070 list_add_tail(&pTL
->implib_list
, &import
->entry
);
4072 ref_type
->pImpTLInfo
= import
;
4074 /* Store a reference to IDispatch */
4075 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
4076 pTL
->dispatch_href
= typelib_ref
;
4078 } else { /* internal ref */
4079 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
4081 ref_type
->reference
= typelib_ref
;
4082 ref_type
->index
= type_num
;
4085 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
4087 table
->refs
[ref
] = typelib_ref
;
4090 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
4091 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
4092 dump_TLBRefType(pTL
);
4096 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
4097 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
4099 SLTG_ImplInfo
*info
;
4100 TLBImplType
*pImplType
;
4101 /* I don't really get this structure, usually it's 0x16 bytes
4102 long, but iuser.tlb contains some that are 0x18 bytes long.
4103 That's ok because we can use the next ptr to jump to the next
4104 one. But how do we know the length of the last one? The WORD
4105 at offs 0x8 might be the clue. For now I'm just assuming that
4106 the last one is the regular 0x16 bytes. */
4108 info
= (SLTG_ImplInfo
*)pBlk
;
4111 if(info
->next
== 0xffff)
4113 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4116 info
= (SLTG_ImplInfo
*)pBlk
;
4117 pTI
->impltypes
= TLBImplType_Alloc(pTI
->cImplTypes
);
4118 pImplType
= pTI
->impltypes
;
4120 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4121 pImplType
->implflags
= info
->impltypeflags
;
4124 if(info
->next
== 0xffff)
4127 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4128 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4130 info
++; /* see comment at top of function */
4134 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4135 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4137 TLBVarDesc
*pVarDesc
;
4138 const TLBString
*prevName
= NULL
;
4139 SLTG_Variable
*pItem
;
4143 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4145 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4146 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4148 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4150 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4151 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4152 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4156 if (pItem
->name
== 0xfffe)
4157 pVarDesc
->Name
= prevName
;
4159 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4161 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4162 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4163 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4165 if(pItem
->flags
& 0x02)
4166 pType
= &pItem
->type
;
4168 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4170 if (pItem
->flags
& ~0xda)
4171 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4173 SLTG_DoElem(pType
, pBlk
,
4174 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4176 if (TRACE_ON(typelib
)) {
4178 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4179 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4182 if (pItem
->flags
& 0x40) {
4183 TRACE_(typelib
)("VAR_DISPATCH\n");
4184 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4186 else if (pItem
->flags
& 0x10) {
4187 TRACE_(typelib
)("VAR_CONST\n");
4188 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4189 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4190 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4191 if (pItem
->flags
& 0x08)
4192 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4194 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4200 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4202 TRACE_(typelib
)("len = %u\n", len
);
4203 if (len
== 0xffff) {
4206 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4207 str
= SysAllocStringLen(NULL
, alloc_len
);
4208 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4210 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4211 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4220 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4221 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4224 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4229 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4230 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4231 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4234 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4235 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4237 if (pItem
->flags
& 0x80)
4238 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4240 prevName
= pVarDesc
->Name
;
4245 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4246 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4248 SLTG_Function
*pFunc
;
4250 TLBFuncDesc
*pFuncDesc
;
4252 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4254 pFuncDesc
= pTI
->funcdescs
;
4255 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4256 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4261 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4262 case SLTG_FUNCTION_MAGIC
:
4263 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4265 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4266 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4268 case SLTG_STATIC_FUNCTION_MAGIC
:
4269 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4272 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4275 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4277 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4278 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4279 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4280 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4281 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4282 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4284 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4285 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4287 if(pFunc
->retnextopt
& 0x80)
4288 pType
= &pFunc
->rettype
;
4290 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4292 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4294 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4295 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4296 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4298 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4300 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4301 char *paramName
= pNameTable
+ *pArg
;
4303 /* If arg type follows then paramName points to the 2nd
4304 letter of the name, else the next WORD is an offset to
4305 the arg type and paramName points to the first letter.
4306 So let's take one char off paramName and see if we're
4307 pointing at an alpha-numeric char. However if *pArg is
4308 0xffff or 0xfffe then the param has no name, the former
4309 meaning that the next WORD is the type, the latter
4310 meaning that the next WORD is an offset to the type. */
4315 else if(*pArg
== 0xfffe) {
4319 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4324 if(HaveOffs
) { /* the next word is an offset to type */
4325 pType
= (WORD
*)(pBlk
+ *pArg
);
4326 SLTG_DoElem(pType
, pBlk
,
4327 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4332 pArg
= SLTG_DoElem(pArg
, pBlk
,
4333 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4336 /* Are we an optional param ? */
4337 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4338 pFuncDesc
->funcdesc
.cParamsOpt
)
4339 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4342 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4343 paramName
- pNameTable
, pTI
->pTypeLib
);
4345 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4349 pTI
->cFuncs
= cFuncs
;
4352 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4353 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4354 SLTG_TypeInfoTail
*pTITail
)
4357 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4359 if(pTIHeader
->href_table
!= 0xffffffff) {
4360 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4366 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4367 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4369 heap_free(ref_lookup
);
4373 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4374 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4375 const SLTG_TypeInfoTail
*pTITail
)
4378 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4380 if(pTIHeader
->href_table
!= 0xffffffff) {
4381 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4387 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4388 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4391 if (pTITail
->funcs_off
!= 0xffff)
4392 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4394 heap_free(ref_lookup
);
4396 if (TRACE_ON(typelib
))
4397 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4400 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4401 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4402 const SLTG_TypeInfoTail
*pTITail
)
4404 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4407 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4408 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4409 const SLTG_TypeInfoTail
*pTITail
)
4412 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4414 if (pTITail
->simple_alias
) {
4415 /* if simple alias, no more processing required */
4416 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4417 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4421 if(pTIHeader
->href_table
!= 0xffffffff) {
4422 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4426 /* otherwise it is an offset to a type */
4427 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4429 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4430 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4432 heap_free(ref_lookup
);
4435 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4436 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4437 const SLTG_TypeInfoTail
*pTITail
)
4439 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4440 if (pTIHeader
->href_table
!= 0xffffffff)
4441 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4444 if (pTITail
->vars_off
!= 0xffff)
4445 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4447 if (pTITail
->funcs_off
!= 0xffff)
4448 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4450 if (pTITail
->impls_off
!= 0xffff)
4451 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4453 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4454 * of dispinterface functions including the IDispatch ones, so
4455 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4456 pTI
->cbSizeVft
= pTI
->cFuncs
* pTI
->pTypeLib
->ptr_size
;
4458 heap_free(ref_lookup
);
4459 if (TRACE_ON(typelib
))
4460 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4463 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4464 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4465 const SLTG_TypeInfoTail
*pTITail
)
4467 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4470 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4471 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4472 const SLTG_TypeInfoTail
*pTITail
)
4474 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4475 if (pTIHeader
->href_table
!= 0xffffffff)
4476 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4479 if (pTITail
->vars_off
!= 0xffff)
4480 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4482 if (pTITail
->funcs_off
!= 0xffff)
4483 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4484 heap_free(ref_lookup
);
4485 if (TRACE_ON(typelib
))
4489 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4490 manageable copy of it into this */
4503 } SLTG_InternalOtherTypeInfo
;
4505 /****************************************************************************
4506 * ITypeLib2_Constructor_SLTG
4508 * loading a SLTG typelib from an in-memory image
4510 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4512 ITypeLibImpl
*pTypeLibImpl
;
4513 SLTG_Header
*pHeader
;
4514 SLTG_BlkEntry
*pBlkEntry
;
4518 LPVOID pBlk
, pFirstBlk
;
4519 SLTG_LibBlk
*pLibBlk
;
4520 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4521 char *pAfterOTIBlks
= NULL
;
4522 char *pNameTable
, *ptr
;
4525 ITypeInfoImpl
**ppTypeInfoImpl
;
4527 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4530 pTypeLibImpl
= TypeLibImpl_Constructor();
4531 if (!pTypeLibImpl
) return NULL
;
4535 TRACE_(typelib
)("header:\n");
4536 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4537 pHeader
->nrOfFileBlks
);
4538 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4539 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4540 pHeader
->SLTG_magic
);
4544 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4545 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4547 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4548 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4550 /* Next we have a magic block */
4551 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4553 /* Let's see if we're still in sync */
4554 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4555 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4556 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4559 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4560 sizeof(SLTG_DIR_MAGIC
))) {
4561 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4565 pIndex
= (SLTG_Index
*)(pMagic
+1);
4567 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4569 pFirstBlk
= pPad9
+ 1;
4571 /* We'll set up a ptr to the main library block, which is the last one. */
4573 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4574 pBlkEntry
[order
].next
!= 0;
4575 order
= pBlkEntry
[order
].next
- 1, i
++) {
4576 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4580 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4582 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4587 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4589 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4592 ptr
= (char*)pLibBlk
+ len
;
4594 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4598 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4600 w
= *(WORD
*)(ptr
+ 2);
4603 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4604 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4605 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4607 w
= *(WORD
*)(ptr
+ 4 + len
);
4609 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4611 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4612 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4613 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4615 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4616 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4617 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4619 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4620 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4623 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4624 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4625 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4626 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4627 len
+= sizeof(SLTG_OtherTypeInfo
);
4631 pAfterOTIBlks
= ptr
;
4633 /* Skip this WORD and get the next DWORD */
4634 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4636 /* Now add this to pLibBLk look at what we're pointing at and
4637 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4638 dust and we should be pointing at the beginning of the name
4641 pNameTable
= (char*)pLibBlk
+ len
;
4643 switch(*(WORD
*)pNameTable
) {
4650 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4654 pNameTable
+= 0x216;
4658 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4660 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4663 /* Hopefully we now have enough ptrs set up to actually read in
4664 some TypeInfos. It's not clear which order to do them in, so
4665 I'll just follow the links along the BlkEntry chain and read
4666 them in the order in which they are in the file */
4668 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4669 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4671 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4672 pBlkEntry
[order
].next
!= 0;
4673 order
= pBlkEntry
[order
].next
- 1, i
++) {
4675 SLTG_TypeInfoHeader
*pTIHeader
;
4676 SLTG_TypeInfoTail
*pTITail
;
4677 SLTG_MemberHeader
*pMemHeader
;
4679 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4680 FIXME_(typelib
)("Index strings don't match\n");
4681 heap_free(pOtherTypeInfoBlks
);
4686 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4687 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4688 heap_free(pOtherTypeInfoBlks
);
4691 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4692 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4693 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4695 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4696 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4697 (*ppTypeInfoImpl
)->index
= i
;
4698 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4699 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4700 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4701 (*ppTypeInfoImpl
)->typekind
= pTIHeader
->typekind
;
4702 (*ppTypeInfoImpl
)->wMajorVerNum
= pTIHeader
->major_version
;
4703 (*ppTypeInfoImpl
)->wMinorVerNum
= pTIHeader
->minor_version
;
4704 (*ppTypeInfoImpl
)->wTypeFlags
=
4705 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4707 if((*ppTypeInfoImpl
)->wTypeFlags
& TYPEFLAG_FDUAL
)
4708 (*ppTypeInfoImpl
)->typekind
= TKIND_DISPATCH
;
4710 if((pTIHeader
->typeflags1
& 7) != 2)
4711 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4712 if(pTIHeader
->typeflags3
!= 2)
4713 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4715 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4716 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4717 typekind_desc
[pTIHeader
->typekind
],
4718 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4719 (*ppTypeInfoImpl
)->wTypeFlags
);
4721 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4723 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4725 (*ppTypeInfoImpl
)->cbAlignment
= pTITail
->cbAlignment
;
4726 (*ppTypeInfoImpl
)->cbSizeInstance
= pTITail
->cbSizeInstance
;
4727 (*ppTypeInfoImpl
)->cbSizeVft
= pTITail
->cbSizeVft
;
4729 switch(pTIHeader
->typekind
) {
4731 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4732 pTIHeader
, pTITail
);
4736 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4737 pTIHeader
, pTITail
);
4740 case TKIND_INTERFACE
:
4741 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4742 pTIHeader
, pTITail
);
4746 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4747 pTIHeader
, pTITail
);
4751 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4752 pTIHeader
, pTITail
);
4755 case TKIND_DISPATCH
:
4756 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4757 pTIHeader
, pTITail
);
4761 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4762 pTIHeader
, pTITail
);
4766 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4771 /* could get cFuncs, cVars and cImplTypes from here
4772 but we've already set those */
4773 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4789 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4792 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4793 FIXME("Somehow processed %d TypeInfos\n", i
);
4794 heap_free(pOtherTypeInfoBlks
);
4798 heap_free(pOtherTypeInfoBlks
);
4799 return &pTypeLibImpl
->ITypeLib2_iface
;
4802 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4804 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4806 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4808 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4809 IsEqualIID(riid
,&IID_ITypeLib
)||
4810 IsEqualIID(riid
,&IID_ITypeLib2
))
4812 *ppv
= &This
->ITypeLib2_iface
;
4814 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4815 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4817 *ppv
= &This
->ICreateTypeLib2_iface
;
4822 TRACE("-- Interface: E_NOINTERFACE\n");
4823 return E_NOINTERFACE
;
4826 IUnknown_AddRef((IUnknown
*)*ppv
);
4830 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4832 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4833 ULONG ref
= InterlockedIncrement(&This
->ref
);
4835 TRACE("(%p) ref=%u\n", This
, ref
);
4840 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4842 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4843 ULONG ref
= InterlockedDecrement(&This
->ref
);
4845 TRACE("(%p) ref=%u\n",This
, ref
);
4849 TLBImpLib
*pImpLib
, *pImpLibNext
;
4850 TLBRefType
*ref_type
;
4851 TLBString
*tlbstr
, *tlbstr_next
;
4852 TLBGuid
*tlbguid
, *tlbguid_next
;
4856 /* remove cache entry */
4859 TRACE("removing from cache list\n");
4860 EnterCriticalSection(&cache_section
);
4861 if(This
->entry
.next
)
4862 list_remove(&This
->entry
);
4863 LeaveCriticalSection(&cache_section
);
4864 heap_free(This
->path
);
4866 TRACE(" destroying ITypeLib(%p)\n",This
);
4868 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4869 list_remove(&tlbstr
->entry
);
4870 SysFreeString(tlbstr
->str
);
4874 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4875 list_remove(&tlbstr
->entry
);
4876 SysFreeString(tlbstr
->str
);
4880 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4881 list_remove(&tlbguid
->entry
);
4885 TLB_FreeCustData(&This
->custdata_list
);
4887 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4888 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4889 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4891 heap_free(This
->pTypeDesc
);
4893 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4895 if (pImpLib
->pImpTypeLib
)
4896 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4897 SysFreeString(pImpLib
->name
);
4899 list_remove(&pImpLib
->entry
);
4903 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4905 list_remove(&ref_type
->entry
);
4906 heap_free(ref_type
);
4909 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4910 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4911 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4913 heap_free(This
->typeinfos
);
4921 /* ITypeLib::GetTypeInfoCount
4923 * Returns the number of type descriptions in the type library
4925 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4927 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4928 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4929 return This
->TypeInfoCount
;
4932 /* ITypeLib::GetTypeInfo
4934 * retrieves the specified type description in the library.
4936 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4939 ITypeInfo
**ppTInfo
)
4941 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4943 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4946 return E_INVALIDARG
;
4948 if(index
>= This
->TypeInfoCount
)
4949 return TYPE_E_ELEMENTNOTFOUND
;
4951 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4952 ITypeInfo_AddRef(*ppTInfo
);
4958 /* ITypeLibs::GetTypeInfoType
4960 * Retrieves the type of a type description.
4962 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4967 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4969 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4972 return E_INVALIDARG
;
4974 if(index
>= This
->TypeInfoCount
)
4975 return TYPE_E_ELEMENTNOTFOUND
;
4977 *pTKind
= This
->typeinfos
[index
]->typekind
;
4982 /* ITypeLib::GetTypeInfoOfGuid
4984 * Retrieves the type description that corresponds to the specified GUID.
4987 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4990 ITypeInfo
**ppTInfo
)
4992 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4995 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4997 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4998 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4999 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
5000 ITypeInfo_AddRef(*ppTInfo
);
5005 return TYPE_E_ELEMENTNOTFOUND
;
5008 /* ITypeLib::GetLibAttr
5010 * Retrieves the structure that contains the library's attributes.
5013 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
5017 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5019 TRACE("(%p, %p)\n", This
, attr
);
5021 if (!attr
) return E_INVALIDARG
;
5023 *attr
= heap_alloc(sizeof(**attr
));
5024 if (!*attr
) return E_OUTOFMEMORY
;
5026 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
5027 (*attr
)->lcid
= This
->set_lcid
;
5028 (*attr
)->syskind
= This
->syskind
;
5029 (*attr
)->wMajorVerNum
= This
->ver_major
;
5030 (*attr
)->wMinorVerNum
= This
->ver_minor
;
5031 (*attr
)->wLibFlags
= This
->libflags
;
5036 /* ITypeLib::GetTypeComp
5038 * Enables a client compiler to bind to a library's types, variables,
5039 * constants, and global functions.
5042 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
5044 ITypeComp
**ppTComp
)
5046 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5048 TRACE("(%p)->(%p)\n",This
,ppTComp
);
5049 *ppTComp
= &This
->ITypeComp_iface
;
5050 ITypeComp_AddRef(*ppTComp
);
5055 /* ITypeLib::GetDocumentation
5057 * Retrieves the library's documentation string, the complete Help file name
5058 * and path, and the context identifier for the library Help topic in the Help
5061 * On a successful return all non-null BSTR pointers will have been set,
5064 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
5068 BSTR
*pBstrDocString
,
5069 DWORD
*pdwHelpContext
,
5070 BSTR
*pBstrHelpFile
)
5072 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5073 HRESULT result
= E_INVALIDARG
;
5076 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
5078 pBstrName
, pBstrDocString
,
5079 pdwHelpContext
, pBstrHelpFile
);
5083 /* documentation for the typelib */
5088 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
5096 if (This
->DocString
)
5098 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
5102 *pBstrDocString
= NULL
;
5106 *pdwHelpContext
= This
->dwHelpContext
;
5112 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5116 *pBstrHelpFile
= NULL
;
5123 /* for a typeinfo */
5124 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5126 if(SUCCEEDED(result
))
5128 result
= ITypeInfo_GetDocumentation(pTInfo
,
5132 pdwHelpContext
, pBstrHelpFile
);
5134 ITypeInfo_Release(pTInfo
);
5139 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5141 if (pBstrName
) SysFreeString (*pBstrName
);
5143 return STG_E_INSUFFICIENTMEMORY
;
5148 * Indicates whether a passed-in string contains the name of a type or member
5149 * described in the library.
5152 static HRESULT WINAPI
ITypeLib2_fnIsName(
5158 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5160 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5162 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5166 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5167 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5168 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5169 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5170 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5172 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5173 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5174 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5175 goto ITypeLib2_fnIsName_exit
;
5178 for(vrc
= 0; vrc
< pTInfo
->cVars
; ++vrc
){
5179 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5180 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5186 ITypeLib2_fnIsName_exit
:
5187 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5188 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5193 /* ITypeLib::FindName
5195 * Finds occurrences of a type description in a type library. This may be used
5196 * to quickly verify that a name exists in a type library.
5199 static HRESULT WINAPI
ITypeLib2_fnFindName(
5203 ITypeInfo
**ppTInfo
,
5207 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5212 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5214 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5215 return E_INVALIDARG
;
5217 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5218 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5219 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5223 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5224 memid
[count
] = MEMBERID_NIL
;
5225 goto ITypeLib2_fnFindName_exit
;
5228 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5229 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5231 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5232 memid
[count
] = func
->funcdesc
.memid
;
5233 goto ITypeLib2_fnFindName_exit
;
5237 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->cVars
, name
);
5239 memid
[count
] = var
->vardesc
.memid
;
5240 goto ITypeLib2_fnFindName_exit
;
5244 ITypeLib2_fnFindName_exit
:
5245 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5246 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5249 TRACE("found %d typeinfos\n", count
);
5256 /* ITypeLib::ReleaseTLibAttr
5258 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5261 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5263 TLIBATTR
*pTLibAttr
)
5265 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5266 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5267 heap_free(pTLibAttr
);
5270 /* ITypeLib2::GetCustData
5272 * gets the custom data
5274 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5279 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5280 TLBCustData
*pCData
;
5282 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5284 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5286 return TYPE_E_ELEMENTNOTFOUND
;
5288 VariantInit(pVarVal
);
5289 VariantCopy(pVarVal
, &pCData
->data
);
5294 /* ITypeLib2::GetLibStatistics
5296 * Returns statistics about a type library that are required for efficient
5297 * sizing of hash tables.
5300 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5302 ULONG
*pcUniqueNames
,
5303 ULONG
*pcchUniqueNames
)
5305 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5307 FIXME("(%p): stub!\n", This
);
5309 if(pcUniqueNames
) *pcUniqueNames
=1;
5310 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5314 /* ITypeLib2::GetDocumentation2
5316 * Retrieves the library's documentation string, the complete Help file name
5317 * and path, the localization context to use, and the context ID for the
5318 * library Help topic in the Help file.
5321 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5325 BSTR
*pbstrHelpString
,
5326 DWORD
*pdwHelpStringContext
,
5327 BSTR
*pbstrHelpStringDll
)
5329 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5333 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5335 /* the help string should be obtained from the helpstringdll,
5336 * using the _DLLGetDocumentation function, based on the supplied
5337 * lcid. Nice to do sometime...
5341 /* documentation for the typelib */
5343 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5344 if(pdwHelpStringContext
)
5345 *pdwHelpStringContext
=This
->dwHelpContext
;
5346 if(pbstrHelpStringDll
)
5347 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5353 /* for a typeinfo */
5354 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5356 if(SUCCEEDED(result
))
5358 ITypeInfo2
* pTInfo2
;
5359 result
= ITypeInfo_QueryInterface(pTInfo
,
5361 (LPVOID
*) &pTInfo2
);
5363 if(SUCCEEDED(result
))
5365 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5369 pdwHelpStringContext
,
5370 pbstrHelpStringDll
);
5372 ITypeInfo2_Release(pTInfo2
);
5375 ITypeInfo_Release(pTInfo
);
5381 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5383 TLBCustData
*pCData
;
5387 ct
= list_count(custdata_list
);
5389 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5390 if(!pCustData
->prgCustData
)
5391 return E_OUTOFMEMORY
;
5393 pCustData
->cCustData
= ct
;
5395 cdi
= pCustData
->prgCustData
;
5396 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5397 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5398 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5406 /* ITypeLib2::GetAllCustData
5408 * Gets all custom data items for the library.
5411 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5413 CUSTDATA
*pCustData
)
5415 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5416 TRACE("(%p)->(%p)\n", This
, pCustData
);
5417 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5420 static const ITypeLib2Vtbl tlbvt
= {
5421 ITypeLib2_fnQueryInterface
,
5423 ITypeLib2_fnRelease
,
5424 ITypeLib2_fnGetTypeInfoCount
,
5425 ITypeLib2_fnGetTypeInfo
,
5426 ITypeLib2_fnGetTypeInfoType
,
5427 ITypeLib2_fnGetTypeInfoOfGuid
,
5428 ITypeLib2_fnGetLibAttr
,
5429 ITypeLib2_fnGetTypeComp
,
5430 ITypeLib2_fnGetDocumentation
,
5432 ITypeLib2_fnFindName
,
5433 ITypeLib2_fnReleaseTLibAttr
,
5435 ITypeLib2_fnGetCustData
,
5436 ITypeLib2_fnGetLibStatistics
,
5437 ITypeLib2_fnGetDocumentation2
,
5438 ITypeLib2_fnGetAllCustData
5442 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5444 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5446 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5449 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5451 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5453 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5456 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5458 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5460 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5463 static HRESULT WINAPI
ITypeLibComp_fnBind(
5468 ITypeInfo
** ppTInfo
,
5469 DESCKIND
* pDescKind
,
5472 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5473 BOOL typemismatch
= FALSE
;
5476 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5478 *pDescKind
= DESCKIND_NONE
;
5479 pBindPtr
->lptcomp
= NULL
;
5482 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5483 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5484 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5486 /* FIXME: check wFlags here? */
5487 /* FIXME: we should use a hash table to look this info up using lHash
5488 * instead of an O(n) search */
5489 if ((pTypeInfo
->typekind
== TKIND_ENUM
) ||
5490 (pTypeInfo
->typekind
== TKIND_MODULE
))
5492 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5494 *pDescKind
= DESCKIND_TYPECOMP
;
5495 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5496 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5497 TRACE("module or enum: %s\n", debugstr_w(szName
));
5502 if ((pTypeInfo
->typekind
== TKIND_MODULE
) ||
5503 (pTypeInfo
->typekind
== TKIND_ENUM
))
5505 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5508 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5509 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5511 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5514 else if (hr
== TYPE_E_TYPEMISMATCH
)
5515 typemismatch
= TRUE
;
5518 if ((pTypeInfo
->typekind
== TKIND_COCLASS
) &&
5519 (pTypeInfo
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5521 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5523 ITypeInfo
*subtypeinfo
;
5525 DESCKIND subdesckind
;
5527 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5528 &subtypeinfo
, &subdesckind
, &subbindptr
);
5529 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5531 TYPEDESC tdesc_appobject
;
5532 const VARDESC vardesc_appobject
=
5535 NULL
, /* lpstrSchema */
5550 VAR_STATIC
/* varkind */
5553 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5554 tdesc_appobject
.vt
= VT_USERDEFINED
;
5556 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5558 /* cleanup things filled in by Bind call so we can put our
5559 * application object data in there instead */
5560 switch (subdesckind
)
5562 case DESCKIND_FUNCDESC
:
5563 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5565 case DESCKIND_VARDESC
:
5566 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5571 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5573 if (pTypeInfo
->hreftype
== -1)
5574 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5576 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5580 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5581 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5582 ITypeInfo_AddRef(*ppTInfo
);
5585 else if (hr
== TYPE_E_TYPEMISMATCH
)
5586 typemismatch
= TRUE
;
5592 TRACE("type mismatch %s\n", debugstr_w(szName
));
5593 return TYPE_E_TYPEMISMATCH
;
5597 TRACE("name not found %s\n", debugstr_w(szName
));
5602 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5606 ITypeInfo
** ppTInfo
,
5607 ITypeComp
** ppTComp
)
5609 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5610 ITypeInfoImpl
*info
;
5612 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5614 if(!szName
|| !ppTInfo
|| !ppTComp
)
5615 return E_INVALIDARG
;
5617 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5624 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5625 ITypeInfo_AddRef(*ppTInfo
);
5626 *ppTComp
= &info
->ITypeComp_iface
;
5627 ITypeComp_AddRef(*ppTComp
);
5632 static const ITypeCompVtbl tlbtcvt
=
5635 ITypeLibComp_fnQueryInterface
,
5636 ITypeLibComp_fnAddRef
,
5637 ITypeLibComp_fnRelease
,
5639 ITypeLibComp_fnBind
,
5640 ITypeLibComp_fnBindType
5643 /*================== ITypeInfo(2) Methods ===================================*/
5644 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5646 ITypeInfoImpl
*pTypeInfoImpl
;
5648 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5651 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5652 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5653 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5654 pTypeInfoImpl
->ref
= 0;
5655 pTypeInfoImpl
->hreftype
= -1;
5656 pTypeInfoImpl
->memidConstructor
= MEMBERID_NIL
;
5657 pTypeInfoImpl
->memidDestructor
= MEMBERID_NIL
;
5658 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5659 list_init(pTypeInfoImpl
->pcustdata_list
);
5661 TRACE("(%p)\n", pTypeInfoImpl
);
5662 return pTypeInfoImpl
;
5665 /* ITypeInfo::QueryInterface
5667 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5672 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5674 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5677 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5678 IsEqualIID(riid
,&IID_ITypeInfo
)||
5679 IsEqualIID(riid
,&IID_ITypeInfo2
))
5681 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5682 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5683 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5686 ITypeInfo2_AddRef(iface
);
5687 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5690 TRACE("-- Interface: E_NOINTERFACE\n");
5691 return E_NOINTERFACE
;
5694 /* ITypeInfo::AddRef
5696 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5698 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5699 ULONG ref
= InterlockedIncrement(&This
->ref
);
5701 TRACE("(%p)->ref is %u\n",This
, ref
);
5703 if (ref
== 1 /* incremented from 0 */)
5704 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5709 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5713 TRACE("destroying ITypeInfo(%p)\n",This
);
5715 for (i
= 0; i
< This
->cFuncs
; ++i
)
5718 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5719 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5721 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5722 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5723 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5724 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5726 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5727 heap_free(pFInfo
->pParamDesc
);
5728 TLB_FreeCustData(&pFInfo
->custdata_list
);
5730 heap_free(This
->funcdescs
);
5732 for(i
= 0; i
< This
->cVars
; ++i
)
5734 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5735 if (pVInfo
->vardesc_create
) {
5736 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5737 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5738 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5739 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5741 TLB_FreeCustData(&pVInfo
->custdata_list
);
5743 heap_free(This
->vardescs
);
5745 if(This
->impltypes
){
5746 for (i
= 0; i
< This
->cImplTypes
; ++i
){
5747 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5748 TLB_FreeCustData(&pImpl
->custdata_list
);
5750 heap_free(This
->impltypes
);
5753 TLB_FreeCustData(&This
->custdata_list
);
5758 /* ITypeInfo::Release
5760 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5762 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5763 ULONG ref
= InterlockedDecrement(&This
->ref
);
5765 TRACE("(%p)->(%u)\n",This
, ref
);
5769 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5770 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5771 if (not_attached_to_typelib
)
5773 /* otherwise This will be freed when typelib is freed */
5779 /* ITypeInfo::GetTypeAttr
5781 * Retrieves a TYPEATTR structure that contains the attributes of the type
5785 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5786 LPTYPEATTR
*ppTypeAttr
)
5788 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5791 TRACE("(%p)\n",This
);
5793 size
= sizeof(**ppTypeAttr
);
5794 if (This
->typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5795 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5797 *ppTypeAttr
= heap_alloc(size
);
5799 return E_OUTOFMEMORY
;
5801 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5802 (*ppTypeAttr
)->lcid
= This
->lcid
;
5803 (*ppTypeAttr
)->memidConstructor
= This
->memidConstructor
;
5804 (*ppTypeAttr
)->memidDestructor
= This
->memidDestructor
;
5805 (*ppTypeAttr
)->lpstrSchema
= This
->lpstrSchema
;
5806 (*ppTypeAttr
)->cbSizeInstance
= This
->cbSizeInstance
;
5807 (*ppTypeAttr
)->typekind
= This
->typekind
;
5808 (*ppTypeAttr
)->cFuncs
= This
->cFuncs
;
5809 (*ppTypeAttr
)->cVars
= This
->cVars
;
5810 (*ppTypeAttr
)->cImplTypes
= This
->cImplTypes
;
5811 (*ppTypeAttr
)->cbSizeVft
= This
->cbSizeVft
;
5812 (*ppTypeAttr
)->cbAlignment
= This
->cbAlignment
;
5813 (*ppTypeAttr
)->wTypeFlags
= This
->wTypeFlags
;
5814 (*ppTypeAttr
)->wMajorVerNum
= This
->wMajorVerNum
;
5815 (*ppTypeAttr
)->wMinorVerNum
= This
->wMinorVerNum
;
5816 (*ppTypeAttr
)->idldescType
= This
->idldescType
;
5818 if (This
->tdescAlias
)
5819 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5820 This
->tdescAlias
, *ppTypeAttr
+ 1);
5822 (*ppTypeAttr
)->tdescAlias
.vt
= VT_EMPTY
;
5823 (*ppTypeAttr
)->tdescAlias
.u
.lptdesc
= NULL
;
5826 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5827 /* This should include all the inherited funcs */
5828 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5829 /* This is always the size of IDispatch's vtbl */
5830 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5831 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5836 /* ITypeInfo::GetTypeComp
5838 * Retrieves the ITypeComp interface for the type description, which enables a
5839 * client compiler to bind to the type description's members.
5842 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5843 ITypeComp
* *ppTComp
)
5845 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5847 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5849 *ppTComp
= &This
->ITypeComp_iface
;
5850 ITypeComp_AddRef(*ppTComp
);
5854 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5856 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5857 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5858 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5862 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5865 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5866 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5868 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5869 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5870 *buffer
+= sizeof(PARAMDESCEX
);
5871 *pparamdescex_dest
= *pparamdescex_src
;
5872 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5873 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5874 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5875 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5878 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5882 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5884 UINT len
= SysStringLen(str
), i
;
5885 for (i
= 0; i
< len
; ++i
)
5891 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5893 if (V_VT(var
) == VT_INT
)
5894 return VariantChangeType(var
, var
, 0, VT_I4
);
5895 else if (V_VT(var
) == VT_UINT
)
5896 return VariantChangeType(var
, var
, 0, VT_UI4
);
5897 else if (V_VT(var
) == VT_BSTR
)
5898 return TLB_SanitizeBSTR(V_BSTR(var
));
5903 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5905 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5906 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5909 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5913 SIZE_T size
= sizeof(*src
);
5917 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5918 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5919 for (i
= 0; i
< src
->cParams
; i
++)
5921 size
+= sizeof(ELEMDESC
);
5922 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5925 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5926 if (!dest
) return E_OUTOFMEMORY
;
5929 if (dispinterface
) /* overwrite funckind */
5930 dest
->funckind
= FUNC_DISPATCH
;
5931 buffer
= (char *)(dest
+ 1);
5933 dest
->oVft
= dest
->oVft
& 0xFFFC;
5935 if (dest
->cScodes
) {
5936 dest
->lprgscode
= (SCODE
*)buffer
;
5937 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5938 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5940 dest
->lprgscode
= NULL
;
5942 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5945 SysFreeString((BSTR
)dest
);
5949 if (dest
->cParams
) {
5950 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5951 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5952 for (i
= 0; i
< src
->cParams
; i
++)
5954 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5960 /* undo the above actions */
5961 for (i
= i
- 1; i
>= 0; i
--)
5962 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5963 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5964 SysFreeString((BSTR
)dest
);
5968 dest
->lprgelemdescParam
= NULL
;
5970 /* special treatment for dispinterfaces: this makes functions appear
5971 * to return their [retval] value when it is really returning an
5973 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5975 if (dest
->cParams
&&
5976 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5978 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5979 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5981 ERR("elemdesc should have started with VT_PTR instead of:\n");
5983 dump_ELEMDESC(elemdesc
);
5984 return E_UNEXPECTED
;
5987 /* copy last parameter to the return value. we are using a flat
5988 * buffer so there is no danger of leaking memory in
5990 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5992 /* remove the last parameter */
5996 /* otherwise this function is made to appear to have no return
5998 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
6006 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
6008 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
6009 if (var_desc
->varkind
== VAR_CONST
)
6010 VariantClear(var_desc
->u
.lpvarValue
);
6011 SysFreeString((BSTR
)var_desc
);
6014 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
6016 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
6018 if (index
>= This
->cFuncs
)
6019 return TYPE_E_ELEMENTNOTFOUND
;
6021 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
6025 /* internal function to make the inherited interfaces' methods appear
6026 * part of the interface */
6027 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
6028 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
6030 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
6032 UINT implemented_funcs
= 0;
6037 *hrefoffset
= DISPATCH_HREF_OFFSET
;
6041 ITypeInfo
*pSubTypeInfo
;
6044 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
6048 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
6051 &sub_funcs
, hrefoffset
);
6052 implemented_funcs
+= sub_funcs
;
6053 ITypeInfo_Release(pSubTypeInfo
);
6056 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
6060 *funcs
= implemented_funcs
+ This
->cFuncs
;
6064 if (index
< implemented_funcs
)
6065 return E_INVALIDARG
;
6066 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
6070 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
6072 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
6075 switch (pTypeDesc
->vt
)
6077 case VT_USERDEFINED
:
6078 pTypeDesc
->u
.hreftype
+= hrefoffset
;
6082 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
6085 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
6093 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
6096 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6097 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
6098 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
6101 /* ITypeInfo::GetFuncDesc
6103 * Retrieves the FUNCDESC structure that contains information about a
6104 * specified function.
6107 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
6108 LPFUNCDESC
*ppFuncDesc
)
6110 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6111 const FUNCDESC
*internal_funcdesc
;
6113 UINT hrefoffset
= 0;
6115 TRACE("(%p) index %d\n", This
, index
);
6118 return E_INVALIDARG
;
6120 if (This
->needs_layout
)
6121 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6123 if (This
->typekind
== TKIND_DISPATCH
)
6124 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
6125 &internal_funcdesc
, NULL
,
6128 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6129 &internal_funcdesc
);
6132 WARN("description for function %d not found\n", index
);
6136 hr
= TLB_AllocAndInitFuncDesc(
6139 This
->typekind
== TKIND_DISPATCH
);
6141 if ((This
->typekind
== TKIND_DISPATCH
) && hrefoffset
)
6142 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6144 TRACE("-- 0x%08x\n", hr
);
6148 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6152 SIZE_T size
= sizeof(*src
);
6155 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6156 if (src
->varkind
== VAR_CONST
)
6157 size
+= sizeof(VARIANT
);
6158 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6160 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6161 if (!dest
) return E_OUTOFMEMORY
;
6164 buffer
= (char *)(dest
+ 1);
6165 if (src
->lpstrSchema
)
6168 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6169 len
= strlenW(src
->lpstrSchema
);
6170 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6171 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6174 if (src
->varkind
== VAR_CONST
)
6178 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6179 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6180 buffer
+= sizeof(VARIANT
);
6181 VariantInit(dest
->u
.lpvarValue
);
6182 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6185 SysFreeString((BSTR
)dest
);
6189 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6192 if (src
->varkind
== VAR_CONST
)
6193 VariantClear(dest
->u
.lpvarValue
);
6194 SysFreeString((BSTR
)dest
);
6201 /* ITypeInfo::GetVarDesc
6203 * Retrieves a VARDESC structure that describes the specified variable.
6206 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6207 LPVARDESC
*ppVarDesc
)
6209 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6210 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6212 TRACE("(%p) index %d\n", This
, index
);
6214 if(index
>= This
->cVars
)
6215 return TYPE_E_ELEMENTNOTFOUND
;
6217 if (This
->needs_layout
)
6218 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6220 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6223 /* ITypeInfo_GetNames
6225 * Retrieves the variable with the specified member ID (or the name of the
6226 * property or method and its parameters) that correspond to the specified
6229 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6230 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6232 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6233 const TLBFuncDesc
*pFDesc
;
6234 const TLBVarDesc
*pVDesc
;
6236 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6239 return E_INVALIDARG
;
6243 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
6246 if(!cMaxNames
|| !pFDesc
->Name
)
6249 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6252 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6253 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6255 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6261 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
6264 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6269 if(This
->impltypes
&&
6270 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
6271 /* recursive search */
6274 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6275 if(SUCCEEDED(result
))
6277 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6278 ITypeInfo_Release(pTInfo
);
6281 WARN("Could not search inherited interface!\n");
6285 WARN("no names found\n");
6288 return TYPE_E_ELEMENTNOTFOUND
;
6294 /* ITypeInfo::GetRefTypeOfImplType
6296 * If a type description describes a COM class, it retrieves the type
6297 * description of the implemented interface types. For an interface,
6298 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6302 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6307 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6310 TRACE("(%p) index %d\n", This
, index
);
6311 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6315 /* only valid on dual interfaces;
6316 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6319 if (This
->wTypeFlags
& TYPEFLAG_FDUAL
)
6325 hr
= TYPE_E_ELEMENTNOTFOUND
;
6328 else if(index
== 0 && This
->typekind
== TKIND_DISPATCH
)
6330 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6331 *pRefType
= This
->pTypeLib
->dispatch_href
;
6335 if(index
>= This
->cImplTypes
)
6336 hr
= TYPE_E_ELEMENTNOTFOUND
;
6338 *pRefType
= This
->impltypes
[index
].hRef
;
6339 if(This
->typekind
== TKIND_INTERFACE
)
6347 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6349 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6355 /* ITypeInfo::GetImplTypeFlags
6357 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6358 * or base interface in a type description.
6360 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6361 UINT index
, INT
*pImplTypeFlags
)
6363 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6365 TRACE("(%p) index %d\n", This
, index
);
6368 return E_INVALIDARG
;
6370 if(This
->typekind
== TKIND_DISPATCH
&& index
== 0){
6371 *pImplTypeFlags
= 0;
6375 if(index
>= This
->cImplTypes
)
6376 return TYPE_E_ELEMENTNOTFOUND
;
6378 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6384 * Maps between member names and member IDs, and parameter names and
6387 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6388 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6390 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6391 const TLBVarDesc
*pVDesc
;
6395 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6398 /* init out parameters in case of failure */
6399 for (i
= 0; i
< cNames
; i
++)
6400 pMemId
[i
] = MEMBERID_NIL
;
6402 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
) {
6404 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6405 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6406 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6407 for(i
=1; i
< cNames
; i
++){
6408 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6409 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6411 if( j
<pFDesc
->funcdesc
.cParams
)
6414 ret
=DISP_E_UNKNOWNNAME
;
6416 TRACE("-- 0x%08x\n", ret
);
6420 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, *rgszNames
);
6423 *pMemId
= pVDesc
->vardesc
.memid
;
6426 /* not found, see if it can be found in an inherited interface */
6427 if(This
->impltypes
) {
6428 /* recursive search */
6430 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6432 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6433 ITypeInfo_Release(pTInfo
);
6436 WARN("Could not search inherited interface!\n");
6438 WARN("no names found\n");
6439 return DISP_E_UNKNOWNNAME
;
6445 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6446 __ASM_GLOBAL_FUNC( call_method
,
6448 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6449 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6450 "movl %esp,%ebp\n\t"
6451 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6453 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6455 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6456 "movl 12(%ebp),%edx\n\t"
6457 "movl %esp,%edi\n\t"
6460 "subl %edx,%edi\n\t"
6461 "andl $~15,%edi\n\t"
6462 "movl %edi,%esp\n\t"
6463 "movl 12(%ebp),%ecx\n\t"
6464 "movl 16(%ebp),%esi\n\t"
6467 "1:\tcall *8(%ebp)\n\t"
6468 "subl %esp,%edi\n\t"
6469 "movl 20(%ebp),%ecx\n\t"
6470 "movl %edi,(%ecx)\n\t"
6471 "leal -8(%ebp),%esp\n\t"
6473 __ASM_CFI(".cfi_same_value %edi\n\t")
6475 __ASM_CFI(".cfi_same_value %esi\n\t")
6477 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6478 __ASM_CFI(".cfi_same_value %ebp\n\t")
6481 /* same function but returning floating point */
6482 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6484 /* ITypeInfo::Invoke
6486 * Invokes a method, or accesses a property of an object, that implements the
6487 * interface described by the type description.
6490 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6494 if (TRACE_ON(ole
)) {
6496 TRACE("Calling %p(",func
);
6497 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6498 if (nrargs
> 30) TRACE("...");
6505 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6508 FIXME("unsupported calling convention %d\n",callconv
);
6512 TRACE("returns %08x\n",res
);
6516 #elif defined(__x86_64__)
6518 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6519 __ASM_GLOBAL_FUNC( call_method
,
6521 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6522 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6523 "movq %rsp,%rbp\n\t"
6524 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6526 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6528 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6529 "movq %rcx,%rax\n\t"
6532 "cmovgq %rdx,%rcx\n\t"
6533 "leaq 0(,%rcx,8),%rdx\n\t"
6534 "subq %rdx,%rsp\n\t"
6535 "andq $~15,%rsp\n\t"
6536 "movq %rsp,%rdi\n\t"
6539 "movq 0(%rsp),%rcx\n\t"
6540 "movq 8(%rsp),%rdx\n\t"
6541 "movq 16(%rsp),%r8\n\t"
6542 "movq 24(%rsp),%r9\n\t"
6543 "movq %rcx,%xmm0\n\t"
6544 "movq %rdx,%xmm1\n\t"
6545 "movq %r8,%xmm2\n\t"
6546 "movq %r9,%xmm3\n\t"
6548 "leaq -16(%rbp),%rsp\n\t"
6550 __ASM_CFI(".cfi_same_value %rdi\n\t")
6552 __ASM_CFI(".cfi_same_value %rsi\n\t")
6553 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6555 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6556 __ASM_CFI(".cfi_same_value %rbp\n\t")
6559 /* same function but returning floating point */
6560 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6562 #endif /* __x86_64__ */
6564 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6567 ITypeInfo
*tinfo2
= NULL
;
6568 TYPEATTR
*tattr
= NULL
;
6570 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6573 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6575 tdesc
->u
.hreftype
, hr
);
6578 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6581 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6582 ITypeInfo_Release(tinfo2
);
6586 switch (tattr
->typekind
)
6593 tdesc
= &tattr
->tdescAlias
;
6594 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6597 case TKIND_INTERFACE
:
6598 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6604 case TKIND_DISPATCH
:
6613 FIXME("TKIND_RECORD unhandled.\n");
6618 FIXME("TKIND_UNION unhandled.\n");
6623 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6627 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6628 ITypeInfo_Release(tinfo2
);
6632 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6636 /* enforce only one level of pointer indirection */
6637 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6639 tdesc
= tdesc
->u
.lptdesc
;
6641 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6642 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6643 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6644 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6645 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6647 VARTYPE vt_userdefined
= 0;
6648 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6649 if (tdesc
->vt
== VT_PTR
)
6651 vt_userdefined
= VT_BYREF
;
6652 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6654 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6656 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6657 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6659 *vt
|= vt_userdefined
;
6671 case VT_USERDEFINED
:
6672 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6679 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6680 hr
= DISP_E_BADVARTYPE
;
6684 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6699 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6705 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6709 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6711 ITypeInfo_Release(tinfo2
);
6715 switch(tattr
->typekind
) {
6717 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6720 case TKIND_INTERFACE
:
6721 case TKIND_DISPATCH
:
6722 *guid
= tattr
->guid
;
6726 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6727 hres
= E_UNEXPECTED
;
6730 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6731 ITypeInfo_Release(tinfo2
);
6735 /***********************************************************************
6736 * DispCallFunc (OLEAUT32.@)
6738 * Invokes a function of the specified calling convention, passing the
6739 * specified arguments and returns the result.
6742 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6743 * oVft [I] The offset in the vtable. See notes.
6744 * cc [I] Calling convention of the function to call.
6745 * vtReturn [I] The return type of the function.
6746 * cActuals [I] Number of parameters.
6747 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6748 * prgpvarg [I] The arguments to pass.
6749 * pvargResult [O] The return value of the function. Can be NULL.
6753 * Failure: HRESULT code.
6756 * The HRESULT return value of this function is not affected by the return
6757 * value of the user supplied function, which is returned in pvargResult.
6759 * If pvInstance is NULL then a non-object function is to be called and oVft
6760 * is the address of the function to call.
6762 * The cc parameter can be one of the following values:
6775 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6776 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6779 int argspos
, stack_offset
;
6784 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6785 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6786 pvargResult
, V_VT(pvargResult
));
6788 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6790 FIXME("unsupported calling convention %d\n",cc
);
6791 return E_INVALIDARG
;
6794 /* maximum size for an argument is sizeof(VARIANT) */
6795 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6797 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6801 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6802 func
= vtable
[oVft
/sizeof(void *)];
6803 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6805 else func
= (void *)oVft
;
6807 for (i
= 0; i
< cActuals
; i
++)
6809 VARIANT
*arg
= prgpvarg
[i
];
6820 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6821 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6825 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6826 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6828 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6829 args
[argspos
++] = V_BOOL(arg
);
6832 args
[argspos
++] = V_UI4(arg
);
6835 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6842 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6845 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6849 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6853 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6854 call_method( func
, argspos
, args
, &stack_offset
);
6859 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6862 WARN("invalid return type %u\n", vtReturn
);
6864 return E_INVALIDARG
;
6866 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6870 if (stack_offset
&& cc
== CC_STDCALL
)
6872 WARN( "stack pointer off by %d\n", stack_offset
);
6873 return DISP_E_BADCALLEE
;
6875 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6876 TRACE("retval: "); dump_Variant(pvargResult
);
6879 #elif defined(__x86_64__)
6885 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6886 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6887 pvargResult
, V_VT(pvargResult
));
6889 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6891 FIXME("unsupported calling convention %d\n",cc
);
6892 return E_INVALIDARG
;
6895 /* maximum size for an argument is sizeof(DWORD_PTR) */
6896 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6898 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6902 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6903 func
= vtable
[oVft
/sizeof(void *)];
6904 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6906 else func
= (void *)oVft
;
6908 for (i
= 0; i
< cActuals
; i
++)
6910 VARIANT
*arg
= prgpvarg
[i
];
6916 args
[argspos
++] = (ULONG_PTR
)arg
;
6918 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6919 args
[argspos
++] = V_BOOL(arg
);
6922 args
[argspos
++] = V_UI8(arg
);
6925 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6932 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6936 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6940 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6941 call_method( func
, argspos
, args
);
6944 WARN("invalid return type %u\n", vtReturn
);
6946 return E_INVALIDARG
;
6948 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6952 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6953 TRACE("retval: "); dump_Variant(pvargResult
);
6957 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6958 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6963 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6965 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6968 #define INVBUF_ELEMENT_SIZE \
6969 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6970 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6971 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6972 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6973 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6974 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6975 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6976 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6978 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6983 DISPPARAMS
*pDispParams
,
6984 VARIANT
*pVarResult
,
6985 EXCEPINFO
*pExcepInfo
,
6988 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6990 unsigned int var_index
;
6993 const TLBFuncDesc
*pFuncInfo
;
6996 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6997 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
7000 if( This
->wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7001 return DISP_E_MEMBERNOTFOUND
;
7005 ERR("NULL pDispParams not allowed\n");
7006 return E_INVALIDARG
;
7009 dump_DispParms(pDispParams
);
7011 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7013 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7014 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7015 return E_INVALIDARG
;
7018 /* we do this instead of using GetFuncDesc since it will return a fake
7019 * FUNCDESC for dispinterfaces and we want the real function description */
7020 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
7021 pFuncInfo
= &This
->funcdescs
[fdc
];
7022 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7023 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7024 !func_restricted( &pFuncInfo
->funcdesc
))
7028 if (fdc
< This
->cFuncs
) {
7029 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7033 TRACE("invoking:\n");
7034 dump_TLBFuncDescOne(pFuncInfo
);
7037 switch (func_desc
->funckind
) {
7038 case FUNC_PUREVIRTUAL
:
7039 case FUNC_VIRTUAL
: {
7040 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7042 VARIANT retval
; /* pointer for storing byref retvals in */
7043 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7044 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7045 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7046 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7047 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7048 UINT vargs_converted
=0;
7052 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7054 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7056 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7057 hres
= DISP_E_PARAMNOTFOUND
;
7062 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7064 ERR("functions with the vararg attribute do not support named arguments\n");
7065 hres
= DISP_E_NONAMEDARGS
;
7069 for (i
= 0; i
< func_desc
->cParams
; i
++)
7071 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7072 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7077 TRACE("changing args\n");
7078 for (i
= 0; i
< func_desc
->cParams
; i
++)
7080 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7081 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7082 VARIANTARG
*src_arg
;
7084 if (wParamFlags
& PARAMFLAG_FLCID
)
7087 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7089 V_I4(arg
) = This
->pTypeLib
->lcid
;
7098 for (j
= 0; j
< cNamedArgs
; j
++)
7099 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7101 src_arg
= &pDispParams
->rgvarg
[j
];
7106 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7108 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7112 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7114 /* under most conditions the caller is not allowed to
7115 * pass in a dispparam arg in the index of what would be
7116 * the retval parameter. however, there is an exception
7117 * where the extra parameter is used in an extra
7118 * IDispatch::Invoke below */
7119 if ((i
< pDispParams
->cArgs
) &&
7120 ((func_desc
->cParams
!= 1) || !pVarResult
||
7121 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7123 hres
= DISP_E_BADPARAMCOUNT
;
7127 /* note: this check is placed so that if the caller passes
7128 * in a VARIANTARG for the retval we just ignore it, like
7130 if (i
== func_desc
->cParams
- 1)
7133 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7134 memset(arg
, 0, sizeof(*arg
));
7135 V_VT(arg
) = rgvt
[i
];
7136 memset(&retval
, 0, sizeof(retval
));
7137 V_BYREF(arg
) = &retval
;
7141 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7142 hres
= E_UNEXPECTED
;
7148 dump_Variant(src_arg
);
7150 if(rgvt
[i
]!=V_VT(src_arg
))
7152 if (rgvt
[i
] == VT_VARIANT
)
7153 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7154 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7156 if (rgvt
[i
] == V_VT(src_arg
))
7157 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7160 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7161 if (wParamFlags
& PARAMFLAG_FIN
)
7162 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7163 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7165 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7167 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
7170 SAFEARRAYBOUND bound
;
7174 bound
.cElements
= pDispParams
->cArgs
-i
;
7175 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7177 ERR("SafeArrayCreate failed\n");
7180 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7183 ERR("SafeArrayAccessData failed with %x\n", hres
);
7184 SafeArrayDestroy(a
);
7187 for (j
= 0; j
< bound
.cElements
; j
++)
7188 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7189 hres
= SafeArrayUnaccessData(a
);
7192 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7193 SafeArrayDestroy(a
);
7196 V_ARRAY(&rgvarg
[i
]) = a
;
7197 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7199 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7201 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7202 if (wParamFlags
& PARAMFLAG_FIN
)
7203 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7205 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7206 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7207 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7209 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7211 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7212 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7216 /* FIXME: this doesn't work for VT_BYREF arguments if
7217 * they are not the same type as in the paramdesc */
7218 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7219 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7220 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7225 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
7226 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
7227 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
7230 prgpvarg
[i
] = &rgvarg
[i
];
7234 prgpvarg
[i
] = src_arg
;
7237 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7238 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7239 && V_UNKNOWN(prgpvarg
[i
])) {
7240 IUnknown
*userdefined_iface
;
7243 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7247 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7249 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7253 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7254 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7257 else if (wParamFlags
& PARAMFLAG_FOPT
)
7260 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7261 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7263 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7269 VARIANTARG
*missing_arg
;
7270 /* if the function wants a pointer to a variant then
7271 * set that up, otherwise just pass the VT_ERROR in
7272 * the argument by value */
7273 if (rgvt
[i
] & VT_BYREF
)
7275 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7276 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7277 V_VARIANTREF(arg
) = missing_arg
;
7281 V_VT(missing_arg
) = VT_ERROR
;
7282 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7287 hres
= DISP_E_BADPARAMCOUNT
;
7291 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7293 /* VT_VOID is a special case for return types, so it is not
7294 * handled in the general function */
7295 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7296 V_VT(&varresult
) = VT_EMPTY
;
7299 V_VT(&varresult
) = 0;
7300 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7301 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7304 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7305 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7306 prgpvarg
, &varresult
);
7308 vargs_converted
= 0;
7310 for (i
= 0; i
< func_desc
->cParams
; i
++)
7312 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7313 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7315 if (wParamFlags
& PARAMFLAG_FLCID
)
7317 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7321 TRACE("[retval] value: ");
7322 dump_Variant(prgpvarg
[i
]);
7327 VariantInit(pVarResult
);
7328 /* deref return value */
7329 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7332 VARIANT_ClearInd(prgpvarg
[i
]);
7334 else if (vargs_converted
< pDispParams
->cArgs
)
7336 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7337 if (wParamFlags
& PARAMFLAG_FOUT
)
7339 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7341 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7345 ERR("failed to convert param %d to vt %d\n", i
,
7346 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7351 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7352 func_desc
->cParamsOpt
< 0 &&
7353 i
== func_desc
->cParams
-1)
7355 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7358 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7361 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7364 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7367 ERR("SafeArrayAccessData failed with %x\n", hres
);
7370 for (j
= 0; j
<= ubound
; j
++)
7371 VariantClear(&v
[j
]);
7372 hres
= SafeArrayUnaccessData(a
);
7375 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7379 VariantClear(&rgvarg
[i
]);
7382 else if (wParamFlags
& PARAMFLAG_FOPT
)
7384 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7385 VariantClear(&rgvarg
[i
]);
7388 VariantClear(&missing_arg
[i
]);
7391 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7393 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7394 hres
= DISP_E_EXCEPTION
;
7397 IErrorInfo
*pErrorInfo
;
7398 pExcepInfo
->scode
= V_ERROR(&varresult
);
7399 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7401 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7402 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7403 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7404 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7406 IErrorInfo_Release(pErrorInfo
);
7410 if (V_VT(&varresult
) != VT_ERROR
)
7412 TRACE("varresult value: ");
7413 dump_Variant(&varresult
);
7417 VariantClear(pVarResult
);
7418 *pVarResult
= varresult
;
7421 VariantClear(&varresult
);
7424 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7425 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7426 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7427 (pDispParams
->cArgs
!= 0))
7429 if (V_VT(pVarResult
) == VT_DISPATCH
)
7431 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7432 /* Note: not VariantClear; we still need the dispatch
7433 * pointer to be valid */
7434 VariantInit(pVarResult
);
7435 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7436 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7437 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7438 IDispatch_Release(pDispatch
);
7442 VariantClear(pVarResult
);
7443 hres
= DISP_E_NOTACOLLECTION
;
7451 case FUNC_DISPATCH
: {
7454 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7455 if (SUCCEEDED(hres
)) {
7456 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7457 hres
= IDispatch_Invoke(
7458 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7459 pVarResult
,pExcepInfo
,pArgErr
7462 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7463 IDispatch_Release(disp
);
7465 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7469 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7474 TRACE("-- 0x%08x\n", hres
);
7477 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7480 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7481 if(FAILED(hres
)) return hres
;
7483 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7484 dump_VARDESC(var_desc
);
7485 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7489 /* not found, look for it in inherited interfaces */
7490 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7491 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7492 if(This
->impltypes
) {
7493 /* recursive search */
7495 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7496 if(SUCCEEDED(hres
)){
7497 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7498 ITypeInfo_Release(pTInfo
);
7501 WARN("Could not search inherited interface!\n");
7504 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7505 return DISP_E_MEMBERNOTFOUND
;
7508 /* ITypeInfo::GetDocumentation
7510 * Retrieves the documentation string, the complete Help file name and path,
7511 * and the context ID for the Help topic for a specified type description.
7513 * (Can be tested by the Visual Basic Editor in Word for instance.)
7515 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7516 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7517 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7519 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7520 const TLBFuncDesc
*pFDesc
;
7521 const TLBVarDesc
*pVDesc
;
7522 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7523 " HelpContext(%p) HelpFile(%p)\n",
7524 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7525 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7527 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7529 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7531 *pdwHelpContext
=This
->dwHelpContext
;
7533 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7535 }else {/* for a member */
7536 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7539 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7541 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7543 *pdwHelpContext
=pFDesc
->helpcontext
;
7545 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7548 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7551 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7553 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7555 *pdwHelpContext
=pVDesc
->HelpContext
;
7557 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7562 if(This
->impltypes
&&
7563 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
7564 /* recursive search */
7567 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7568 if(SUCCEEDED(result
)) {
7569 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7570 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7571 ITypeInfo_Release(pTInfo
);
7574 WARN("Could not search inherited interface!\n");
7577 WARN("member %d not found\n", memid
);
7578 return TYPE_E_ELEMENTNOTFOUND
;
7581 /* ITypeInfo::GetDllEntry
7583 * Retrieves a description or specification of an entry point for a function
7586 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7587 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7590 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7591 const TLBFuncDesc
*pFDesc
;
7593 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7595 if (pBstrDllName
) *pBstrDllName
= NULL
;
7596 if (pBstrName
) *pBstrName
= NULL
;
7597 if (pwOrdinal
) *pwOrdinal
= 0;
7599 if (This
->typekind
!= TKIND_MODULE
)
7600 return TYPE_E_BADMODULEKIND
;
7602 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7604 dump_TypeInfo(This
);
7606 dump_TLBFuncDescOne(pFDesc
);
7609 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7611 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7613 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7621 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7624 return TYPE_E_ELEMENTNOTFOUND
;
7627 /* internal function to make the inherited interfaces' methods appear
7628 * part of the interface */
7629 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7630 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7632 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7635 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7637 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7639 ITypeInfo
*pSubTypeInfo
;
7641 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7645 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7647 ITypeInfo_Release(pSubTypeInfo
);
7651 *hRefType
-= DISPATCH_HREF_OFFSET
;
7653 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7654 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7659 /* ITypeInfo::GetRefTypeInfo
7661 * If a type description references other type descriptions, it retrieves
7662 * the referenced type descriptions.
7664 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7667 ITypeInfo
**ppTInfo
)
7669 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7670 HRESULT result
= E_FAIL
;
7673 return E_INVALIDARG
;
7675 if ((INT
)hRefType
< 0) {
7676 ITypeInfoImpl
*pTypeInfoImpl
;
7678 if (!(This
->wTypeFlags
& TYPEFLAG_FDUAL
) ||
7679 !(This
->typekind
== TKIND_INTERFACE
||
7680 This
->typekind
== TKIND_DISPATCH
))
7681 return TYPE_E_ELEMENTNOTFOUND
;
7683 /* when we meet a DUAL typeinfo, we must create the alternate
7686 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7688 *pTypeInfoImpl
= *This
;
7689 pTypeInfoImpl
->ref
= 0;
7690 list_init(&pTypeInfoImpl
->custdata_list
);
7692 if (This
->typekind
== TKIND_INTERFACE
)
7693 pTypeInfoImpl
->typekind
= TKIND_DISPATCH
;
7695 pTypeInfoImpl
->typekind
= TKIND_INTERFACE
;
7697 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7698 /* the AddRef implicitly adds a reference to the parent typelib, which
7699 * stops the copied data from being destroyed until the new typeinfo's
7700 * refcount goes to zero, but we need to signal to the new instance to
7701 * not free its data structures when it is destroyed */
7702 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7704 ITypeInfo_AddRef(*ppTInfo
);
7707 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7708 (This
->typekind
== TKIND_DISPATCH
))
7710 HREFTYPE href_dispatch
= hRefType
;
7711 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7713 TLBRefType
*ref_type
;
7714 ITypeLib
*pTLib
= NULL
;
7717 if(!(hRefType
& 0x1)){
7718 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7720 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7723 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7724 ITypeInfo_AddRef(*ppTInfo
);
7730 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7732 if(ref_type
->reference
== (hRefType
& (~0x3)))
7735 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7737 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7741 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7743 TRACE("internal reference\n");
7744 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7746 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7747 TRACE("typeinfo in imported typelib that is already loaded\n");
7748 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7749 ITypeLib_AddRef(pTLib
);
7754 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7756 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7757 ref_type
->pImpTLInfo
->wVersionMajor
,
7758 ref_type
->pImpTLInfo
->wVersionMinor
,
7759 This
->pTypeLib
->syskind
,
7760 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7762 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7764 result
= LoadTypeLib(libnam
, &pTLib
);
7765 SysFreeString(libnam
);
7767 if(SUCCEEDED(result
)) {
7768 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7769 ITypeLib_AddRef(pTLib
);
7773 if(SUCCEEDED(result
)) {
7774 if(ref_type
->index
== TLB_REF_USE_GUID
)
7775 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7777 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7780 ITypeLib_Release(pTLib
);
7784 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7785 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7789 /* ITypeInfo::AddressOfMember
7791 * Retrieves the addresses of static functions or variables, such as those
7794 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7795 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7797 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7803 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7805 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7809 module
= LoadLibraryW(dll
);
7812 ERR("couldn't load %s\n", debugstr_w(dll
));
7814 SysFreeString(entry
);
7815 return STG_E_FILENOTFOUND
;
7817 /* FIXME: store library somewhere where we can free it */
7822 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7823 entryA
= heap_alloc(len
);
7824 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7826 *ppv
= GetProcAddress(module
, entryA
);
7828 ERR("function not found %s\n", debugstr_a(entryA
));
7834 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7836 ERR("function not found %d\n", ordinal
);
7840 SysFreeString(entry
);
7843 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7848 /* ITypeInfo::CreateInstance
7850 * Creates a new instance of a type that describes a component object class
7853 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7854 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7856 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7860 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7866 WARN("Not able to aggregate\n");
7867 return CLASS_E_NOAGGREGATION
;
7870 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7871 if(FAILED(hr
)) return hr
;
7873 if(pTA
->typekind
!= TKIND_COCLASS
)
7875 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7881 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7884 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7885 TRACE("GetActiveObject rets %08x\n", hr
);
7888 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7889 IUnknown_Release(pUnk
);
7894 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7895 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7899 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7903 /* ITypeInfo::GetMops
7905 * Retrieves marshalling information.
7907 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7910 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7911 FIXME("(%p %d) stub!\n", This
, memid
);
7916 /* ITypeInfo::GetContainingTypeLib
7918 * Retrieves the containing type library and the index of the type description
7919 * within that type library.
7921 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7922 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7924 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7926 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7928 *pIndex
=This
->index
;
7929 TRACE("returning pIndex=%d\n", *pIndex
);
7933 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7934 ITypeLib_AddRef(*ppTLib
);
7935 TRACE("returning ppTLib=%p\n", *ppTLib
);
7941 /* ITypeInfo::ReleaseTypeAttr
7943 * Releases a TYPEATTR previously returned by Get
7946 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7947 TYPEATTR
* pTypeAttr
)
7949 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7950 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7951 heap_free(pTypeAttr
);
7954 /* ITypeInfo::ReleaseFuncDesc
7956 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7958 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7960 FUNCDESC
*pFuncDesc
)
7962 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7965 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7967 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7968 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7969 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7971 SysFreeString((BSTR
)pFuncDesc
);
7974 /* ITypeInfo::ReleaseVarDesc
7976 * Releases a VARDESC previously returned by GetVarDesc.
7978 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7981 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7982 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7984 TLB_FreeVarDesc(pVarDesc
);
7987 /* ITypeInfo2::GetTypeKind
7989 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7992 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7993 TYPEKIND
*pTypeKind
)
7995 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7996 *pTypeKind
=This
->typekind
;
7997 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8001 /* ITypeInfo2::GetTypeFlags
8003 * Returns the type flags without any allocations. This returns a DWORD type
8004 * flag, which expands the type flags without growing the TYPEATTR (type
8008 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8010 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8011 *pTypeFlags
=This
->wTypeFlags
;
8012 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
8016 /* ITypeInfo2::GetFuncIndexOfMemId
8017 * Binds to a specific member based on a known DISPID, where the member name
8018 * is not known (for example, when binding to a default member).
8021 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8022 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8024 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8028 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8029 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8030 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8033 if(fdc
< This
->cFuncs
) {
8037 result
= TYPE_E_ELEMENTNOTFOUND
;
8039 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
8040 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8044 /* TypeInfo2::GetVarIndexOfMemId
8046 * Binds to a specific member based on a known DISPID, where the member name
8047 * is not known (for example, when binding to a default member).
8050 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8051 MEMBERID memid
, UINT
*pVarIndex
)
8053 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8054 TLBVarDesc
*pVarInfo
;
8056 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8058 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8060 return TYPE_E_ELEMENTNOTFOUND
;
8062 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8067 /* ITypeInfo2::GetCustData
8069 * Gets the custom data
8071 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8076 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8077 TLBCustData
*pCData
;
8079 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8081 if(!guid
|| !pVarVal
)
8082 return E_INVALIDARG
;
8084 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8086 VariantInit( pVarVal
);
8088 VariantCopy( pVarVal
, &pCData
->data
);
8090 VariantClear( pVarVal
);
8094 /* ITypeInfo2::GetFuncCustData
8096 * Gets the custom data
8098 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8104 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8105 TLBCustData
*pCData
;
8106 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8108 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8110 if(index
>= This
->cFuncs
)
8111 return TYPE_E_ELEMENTNOTFOUND
;
8113 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8115 return TYPE_E_ELEMENTNOTFOUND
;
8117 VariantInit(pVarVal
);
8118 VariantCopy(pVarVal
, &pCData
->data
);
8123 /* ITypeInfo2::GetParamCustData
8125 * Gets the custom data
8127 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8134 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8135 TLBCustData
*pCData
;
8136 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8138 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8139 debugstr_guid(guid
), pVarVal
);
8141 if(indexFunc
>= This
->cFuncs
)
8142 return TYPE_E_ELEMENTNOTFOUND
;
8144 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8145 return TYPE_E_ELEMENTNOTFOUND
;
8147 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8149 return TYPE_E_ELEMENTNOTFOUND
;
8151 VariantInit(pVarVal
);
8152 VariantCopy(pVarVal
, &pCData
->data
);
8157 /* ITypeInfo2::GetVarCustData
8159 * Gets the custom data
8161 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8167 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8168 TLBCustData
*pCData
;
8169 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8171 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8173 if(index
>= This
->cVars
)
8174 return TYPE_E_ELEMENTNOTFOUND
;
8176 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8178 return TYPE_E_ELEMENTNOTFOUND
;
8180 VariantInit(pVarVal
);
8181 VariantCopy(pVarVal
, &pCData
->data
);
8186 /* ITypeInfo2::GetImplCustData
8188 * Gets the custom data
8190 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8196 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8197 TLBCustData
*pCData
;
8198 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8200 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8202 if(index
>= This
->cImplTypes
)
8203 return TYPE_E_ELEMENTNOTFOUND
;
8205 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8207 return TYPE_E_ELEMENTNOTFOUND
;
8209 VariantInit(pVarVal
);
8210 VariantCopy(pVarVal
, &pCData
->data
);
8215 /* ITypeInfo2::GetDocumentation2
8217 * Retrieves the documentation string, the complete Help file name and path,
8218 * the localization context to use, and the context ID for the library Help
8219 * topic in the Help file.
8222 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8226 BSTR
*pbstrHelpString
,
8227 DWORD
*pdwHelpStringContext
,
8228 BSTR
*pbstrHelpStringDll
)
8230 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8231 const TLBFuncDesc
*pFDesc
;
8232 const TLBVarDesc
*pVDesc
;
8233 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8234 "HelpStringContext(%p) HelpStringDll(%p)\n",
8235 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8236 pbstrHelpStringDll
);
8237 /* the help string should be obtained from the helpstringdll,
8238 * using the _DLLGetDocumentation function, based on the supplied
8239 * lcid. Nice to do sometime...
8241 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8243 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8244 if(pdwHelpStringContext
)
8245 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8246 if(pbstrHelpStringDll
)
8247 *pbstrHelpStringDll
=
8248 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8250 }else {/* for a member */
8251 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
8254 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8255 if(pdwHelpStringContext
)
8256 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8257 if(pbstrHelpStringDll
)
8258 *pbstrHelpStringDll
=
8259 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8262 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8265 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8266 if(pdwHelpStringContext
)
8267 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8268 if(pbstrHelpStringDll
)
8269 *pbstrHelpStringDll
=
8270 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8274 return TYPE_E_ELEMENTNOTFOUND
;
8277 /* ITypeInfo2::GetAllCustData
8279 * Gets all custom data items for the Type info.
8282 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8284 CUSTDATA
*pCustData
)
8286 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8288 TRACE("%p %p\n", This
, pCustData
);
8290 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8293 /* ITypeInfo2::GetAllFuncCustData
8295 * Gets all custom data items for the specified Function
8298 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8301 CUSTDATA
*pCustData
)
8303 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8304 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8306 TRACE("%p %u %p\n", This
, index
, pCustData
);
8308 if(index
>= This
->cFuncs
)
8309 return TYPE_E_ELEMENTNOTFOUND
;
8311 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8314 /* ITypeInfo2::GetAllParamCustData
8316 * Gets all custom data items for the Functions
8319 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8320 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8322 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8323 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8325 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8327 if(indexFunc
>= This
->cFuncs
)
8328 return TYPE_E_ELEMENTNOTFOUND
;
8330 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8331 return TYPE_E_ELEMENTNOTFOUND
;
8333 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8336 /* ITypeInfo2::GetAllVarCustData
8338 * Gets all custom data items for the specified Variable
8341 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8342 UINT index
, CUSTDATA
*pCustData
)
8344 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8345 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8347 TRACE("%p %u %p\n", This
, index
, pCustData
);
8349 if(index
>= This
->cVars
)
8350 return TYPE_E_ELEMENTNOTFOUND
;
8352 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8355 /* ITypeInfo2::GetAllImplCustData
8357 * Gets all custom data items for the specified implementation type
8360 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8363 CUSTDATA
*pCustData
)
8365 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8366 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8368 TRACE("%p %u %p\n", This
, index
, pCustData
);
8370 if(index
>= This
->cImplTypes
)
8371 return TYPE_E_ELEMENTNOTFOUND
;
8373 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8376 static const ITypeInfo2Vtbl tinfvt
=
8379 ITypeInfo_fnQueryInterface
,
8381 ITypeInfo_fnRelease
,
8383 ITypeInfo_fnGetTypeAttr
,
8384 ITypeInfo_fnGetTypeComp
,
8385 ITypeInfo_fnGetFuncDesc
,
8386 ITypeInfo_fnGetVarDesc
,
8387 ITypeInfo_fnGetNames
,
8388 ITypeInfo_fnGetRefTypeOfImplType
,
8389 ITypeInfo_fnGetImplTypeFlags
,
8390 ITypeInfo_fnGetIDsOfNames
,
8392 ITypeInfo_fnGetDocumentation
,
8393 ITypeInfo_fnGetDllEntry
,
8394 ITypeInfo_fnGetRefTypeInfo
,
8395 ITypeInfo_fnAddressOfMember
,
8396 ITypeInfo_fnCreateInstance
,
8397 ITypeInfo_fnGetMops
,
8398 ITypeInfo_fnGetContainingTypeLib
,
8399 ITypeInfo_fnReleaseTypeAttr
,
8400 ITypeInfo_fnReleaseFuncDesc
,
8401 ITypeInfo_fnReleaseVarDesc
,
8403 ITypeInfo2_fnGetTypeKind
,
8404 ITypeInfo2_fnGetTypeFlags
,
8405 ITypeInfo2_fnGetFuncIndexOfMemId
,
8406 ITypeInfo2_fnGetVarIndexOfMemId
,
8407 ITypeInfo2_fnGetCustData
,
8408 ITypeInfo2_fnGetFuncCustData
,
8409 ITypeInfo2_fnGetParamCustData
,
8410 ITypeInfo2_fnGetVarCustData
,
8411 ITypeInfo2_fnGetImplTypeCustData
,
8412 ITypeInfo2_fnGetDocumentation2
,
8413 ITypeInfo2_fnGetAllCustData
,
8414 ITypeInfo2_fnGetAllFuncCustData
,
8415 ITypeInfo2_fnGetAllParamCustData
,
8416 ITypeInfo2_fnGetAllVarCustData
,
8417 ITypeInfo2_fnGetAllImplTypeCustData
,
8420 /******************************************************************************
8421 * CreateDispTypeInfo [OLEAUT32.31]
8423 * Build type information for an object so it can be called through an
8424 * IDispatch interface.
8427 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8428 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8431 * This call allows an objects methods to be accessed through IDispatch, by
8432 * building an ITypeInfo object that IDispatch can use to call through.
8434 HRESULT WINAPI
CreateDispTypeInfo(
8435 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8436 LCID lcid
, /* [I] Locale Id */
8437 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8439 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8440 ITypeLibImpl
*pTypeLibImpl
;
8441 unsigned int param
, func
;
8442 TLBFuncDesc
*pFuncDesc
;
8446 pTypeLibImpl
= TypeLibImpl_Constructor();
8447 if (!pTypeLibImpl
) return E_FAIL
;
8449 pTypeLibImpl
->TypeInfoCount
= 2;
8450 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8452 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8453 pTIIface
->pTypeLib
= pTypeLibImpl
;
8454 pTIIface
->index
= 0;
8455 pTIIface
->Name
= NULL
;
8456 pTIIface
->dwHelpContext
= -1;
8457 pTIIface
->guid
= NULL
;
8458 pTIIface
->lcid
= lcid
;
8459 pTIIface
->typekind
= TKIND_INTERFACE
;
8460 pTIIface
->wMajorVerNum
= 0;
8461 pTIIface
->wMinorVerNum
= 0;
8462 pTIIface
->cbAlignment
= 2;
8463 pTIIface
->cbSizeInstance
= -1;
8464 pTIIface
->cbSizeVft
= -1;
8465 pTIIface
->cFuncs
= 0;
8466 pTIIface
->cImplTypes
= 0;
8467 pTIIface
->cVars
= 0;
8468 pTIIface
->wTypeFlags
= 0;
8469 pTIIface
->hreftype
= 0;
8471 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8472 pFuncDesc
= pTIIface
->funcdescs
;
8473 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8474 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8475 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8476 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8477 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8478 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8479 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8480 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8481 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8482 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8483 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8484 pFuncDesc
->funcdesc
.cScodes
= 0;
8485 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8486 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8487 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8488 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8489 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8490 md
->cArgs
* sizeof(ELEMDESC
));
8491 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8492 for(param
= 0; param
< md
->cArgs
; param
++) {
8493 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8494 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8496 pFuncDesc
->helpcontext
= 0;
8497 pFuncDesc
->HelpStringContext
= 0;
8498 pFuncDesc
->HelpString
= NULL
;
8499 pFuncDesc
->Entry
= NULL
;
8500 list_init(&pFuncDesc
->custdata_list
);
8505 dump_TypeInfo(pTIIface
);
8507 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8508 pTIClass
->pTypeLib
= pTypeLibImpl
;
8509 pTIClass
->index
= 1;
8510 pTIClass
->Name
= NULL
;
8511 pTIClass
->dwHelpContext
= -1;
8512 pTIClass
->guid
= NULL
;
8513 pTIClass
->lcid
= lcid
;
8514 pTIClass
->typekind
= TKIND_COCLASS
;
8515 pTIClass
->wMajorVerNum
= 0;
8516 pTIClass
->wMinorVerNum
= 0;
8517 pTIClass
->cbAlignment
= 2;
8518 pTIClass
->cbSizeInstance
= -1;
8519 pTIClass
->cbSizeVft
= -1;
8520 pTIClass
->cFuncs
= 0;
8521 pTIClass
->cImplTypes
= 1;
8522 pTIClass
->cVars
= 0;
8523 pTIClass
->wTypeFlags
= 0;
8524 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8526 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8528 ref
= heap_alloc_zero(sizeof(*ref
));
8529 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8530 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8532 dump_TypeInfo(pTIClass
);
8534 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8536 ITypeInfo_AddRef(*pptinfo
);
8537 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8543 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8545 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8547 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8550 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8552 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8554 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8557 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8559 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8561 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8564 static HRESULT WINAPI
ITypeComp_fnBind(
8569 ITypeInfo
** ppTInfo
,
8570 DESCKIND
* pDescKind
,
8573 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8574 const TLBFuncDesc
*pFDesc
;
8575 const TLBVarDesc
*pVDesc
;
8576 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8579 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8581 *pDescKind
= DESCKIND_NONE
;
8582 pBindPtr
->lpfuncdesc
= NULL
;
8585 for(fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8586 pFDesc
= &This
->funcdescs
[fdc
];
8587 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8588 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8591 /* name found, but wrong flags */
8592 hr
= TYPE_E_TYPEMISMATCH
;
8596 if (fdc
< This
->cFuncs
)
8598 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8600 &pBindPtr
->lpfuncdesc
,
8601 This
->typekind
== TKIND_DISPATCH
);
8604 *pDescKind
= DESCKIND_FUNCDESC
;
8605 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8606 ITypeInfo_AddRef(*ppTInfo
);
8609 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, szName
);
8611 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8614 *pDescKind
= DESCKIND_VARDESC
;
8615 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8616 ITypeInfo_AddRef(*ppTInfo
);
8621 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8622 /* recursive search */
8626 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8629 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8630 ITypeInfo_Release(pTInfo
);
8634 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8635 ITypeComp_Release(pTComp
);
8636 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8637 This
->typekind
== TKIND_DISPATCH
)
8639 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8640 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8641 SysFreeString((BSTR
)tmp
);
8645 WARN("Could not search inherited interface!\n");
8647 if (hr
== DISP_E_MEMBERNOTFOUND
)
8649 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8653 static HRESULT WINAPI
ITypeComp_fnBindType(
8657 ITypeInfo
** ppTInfo
,
8658 ITypeComp
** ppTComp
)
8660 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8662 /* strange behaviour (does nothing) but like the
8665 if (!ppTInfo
|| !ppTComp
)
8674 static const ITypeCompVtbl tcompvt
=
8677 ITypeComp_fnQueryInterface
,
8679 ITypeComp_fnRelease
,
8682 ITypeComp_fnBindType
8685 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8686 ICreateTypeLib2
** ppctlib
)
8691 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8693 if (!szFile
) return E_INVALIDARG
;
8695 This
= TypeLibImpl_Constructor();
8697 return E_OUTOFMEMORY
;
8699 This
->lcid
= GetSystemDefaultLCID();
8700 This
->syskind
= syskind
;
8701 This
->ptr_size
= get_ptr_size(syskind
);
8703 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8705 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8706 return E_OUTOFMEMORY
;
8708 lstrcpyW(This
->path
, szFile
);
8710 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8711 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8715 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8716 REFIID riid
, void **object
)
8718 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8720 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8723 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8725 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8727 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8730 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8732 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8734 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8737 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8738 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8740 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8741 ITypeInfoImpl
*info
;
8744 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8746 if (!ctinfo
|| !name
)
8747 return E_INVALIDARG
;
8749 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8751 return TYPE_E_NAMECONFLICT
;
8753 if (This
->typeinfos
)
8754 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8755 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8757 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8759 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8761 info
->pTypeLib
= This
;
8762 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8763 info
->index
= This
->TypeInfoCount
;
8764 info
->typekind
= kind
;
8765 info
->cbAlignment
= 4;
8767 switch(info
->typekind
) {
8769 case TKIND_INTERFACE
:
8770 case TKIND_DISPATCH
:
8772 info
->cbSizeInstance
= This
->ptr_size
;
8776 info
->cbSizeInstance
= 0;
8779 info
->cbSizeInstance
= 2;
8782 info
->cbSizeInstance
= -0x75;
8785 FIXME("unrecognized typekind %d\n", info
->typekind
);
8786 info
->cbSizeInstance
= 0xdeadbeef;
8790 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8791 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8793 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8797 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8799 ++This
->TypeInfoCount
;
8804 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8807 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8809 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8812 return E_INVALIDARG
;
8814 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8819 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8820 WORD majorVerNum
, WORD minorVerNum
)
8822 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8824 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8826 This
->ver_major
= majorVerNum
;
8827 This
->ver_minor
= minorVerNum
;
8832 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8835 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8837 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8839 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8844 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8847 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8849 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8852 return E_INVALIDARG
;
8854 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8859 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8860 LPOLESTR helpFileName
)
8862 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8864 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8867 return E_INVALIDARG
;
8869 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8874 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8877 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8879 TRACE("%p %d\n", This
, helpContext
);
8881 This
->dwHelpContext
= helpContext
;
8886 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8889 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8891 TRACE("%p %x\n", This
, lcid
);
8893 This
->set_lcid
= lcid
;
8898 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8901 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8903 TRACE("%p %x\n", This
, libFlags
);
8905 This
->libflags
= libFlags
;
8910 typedef struct tagWMSFT_SegContents
{
8913 } WMSFT_SegContents
;
8915 typedef struct tagWMSFT_TLBFile
{
8917 WMSFT_SegContents typeinfo_seg
;
8918 WMSFT_SegContents impfile_seg
;
8919 WMSFT_SegContents impinfo_seg
;
8920 WMSFT_SegContents ref_seg
;
8921 WMSFT_SegContents guidhash_seg
;
8922 WMSFT_SegContents guid_seg
;
8923 WMSFT_SegContents namehash_seg
;
8924 WMSFT_SegContents name_seg
;
8925 WMSFT_SegContents string_seg
;
8926 WMSFT_SegContents typdesc_seg
;
8927 WMSFT_SegContents arraydesc_seg
;
8928 WMSFT_SegContents custdata_seg
;
8929 WMSFT_SegContents cdguids_seg
;
8931 WMSFT_SegContents aux_seg
;
8934 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8935 WMSFT_TLBFile
*file
)
8941 file
->string_seg
.len
= 0;
8942 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8945 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8947 return E_UNEXPECTED
;
8949 size
+= sizeof(INT16
);
8951 size
= (size
+ 4) & ~0x3;
8955 file
->string_seg
.len
+= size
;
8957 /* temporarily use str->offset to store the length of the aligned,
8958 * converted string */
8962 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8965 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8968 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8969 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8971 heap_free(file
->string_seg
.data
);
8972 return E_UNEXPECTED
;
8975 *((INT16
*)data
) = size
;
8977 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8981 str
->offset
= last_offs
;
8988 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8989 WMSFT_TLBFile
*file
)
8994 MSFT_NameIntro
*last_intro
= NULL
;
8996 file
->header
.nametablecount
= 0;
8997 file
->header
.nametablechars
= 0;
8999 file
->name_seg
.len
= 0;
9000 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9003 size
= strlenW(str
->str
);
9004 file
->header
.nametablechars
+= size
;
9005 file
->header
.nametablecount
++;
9007 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9009 return E_UNEXPECTED
;
9011 size
+= sizeof(MSFT_NameIntro
);
9013 size
= (size
+ 4) & ~0x3;
9017 file
->name_seg
.len
+= size
;
9019 /* temporarily use str->offset to store the length of the aligned,
9020 * converted string */
9024 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9025 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
9028 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9030 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9032 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
9033 data
+ sizeof(MSFT_NameIntro
),
9034 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9036 heap_free(file
->name_seg
.data
);
9037 return E_UNEXPECTED
;
9039 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9041 intro
->hreftype
= -1; /* TODO? */
9042 intro
->namelen
= size
& 0xFF;
9043 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9044 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9045 intro
->namelen
|= hash
<< 16;
9046 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9047 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9049 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9050 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9052 /* update str->offset to actual value to use in other
9053 * compilation functions that require positions within
9054 * the string table */
9058 str
->offset
= last_offs
;
9063 last_intro
->hreftype
= 0; /* last one is 0? */
9068 static inline int hash_guid(GUID
*guid
)
9072 for (i
= 0; i
< 8; i
++)
9073 hash
^= ((const short *)guid
)[i
];
9078 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9081 MSFT_GuidEntry
*entry
;
9083 int hash_key
, *guidhashtab
;
9085 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9086 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9088 entry
= file
->guid_seg
.data
;
9090 guidhashtab
= file
->guidhash_seg
.data
;
9091 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9092 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9093 entry
->hreftype
= guid
->hreftype
;
9095 hash_key
= hash_guid(&guid
->guid
);
9096 entry
->next_hash
= guidhashtab
[hash_key
];
9097 guidhashtab
[hash_key
] = offs
;
9099 guid
->offset
= offs
;
9100 offs
+= sizeof(MSFT_GuidEntry
);
9107 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9110 VARTYPE arg_type
= V_VT(value
);
9113 DWORD ret
= file
->custdata_seg
.len
;
9115 if(arg_type
== VT_INT
)
9117 if(arg_type
== VT_UINT
)
9121 if(V_VT(value
) != arg_type
) {
9122 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9124 ERR("VariantChangeType failed: %08x\n", hres
);
9129 /* Check if default value can be stored in-place */
9134 if(V_UI4(&v
) > 0x3ffffff)
9147 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9150 /* have to allocate space in custdata_seg */
9159 /* Construct the data to be allocated */
9162 if(file
->custdata_seg
.data
){
9163 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9164 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9165 file
->custdata_seg
.len
+= sizeof(int) * 2;
9167 file
->custdata_seg
.len
= sizeof(int) * 2;
9168 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9171 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9172 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9174 /* TODO: Check if the encoded data is already present in custdata_seg */
9180 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9183 if(file
->custdata_seg
.data
){
9184 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9185 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9186 file
->custdata_seg
.len
+= len
;
9188 file
->custdata_seg
.len
= len
;
9189 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9192 *((unsigned short *)data
) = V_VT(value
);
9193 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9194 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9195 if(V_BSTR(&v
)[i
] <= 0x7f)
9196 data
[i
+6] = V_BSTR(&v
)[i
];
9200 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9201 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9204 /* TODO: Check if the encoded data is already present in custdata_seg */
9209 FIXME("Argument type not yet handled\n");
9214 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9216 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9218 DWORD offs
= file
->arraydesc_seg
.len
;
9222 /* TODO: we should check for duplicates, but that's harder because each
9223 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9224 * at the library-level) */
9226 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9227 if(!file
->arraydesc_seg
.data
)
9228 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9230 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9231 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
) + offs
;
9233 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9234 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9235 for(i
= 0; i
< desc
->cDims
; ++i
){
9236 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9237 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9243 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9249 VARTYPE vt
, subtype
;
9260 vt
= desc
->vt
& VT_TYPEMASK
;
9262 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9264 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9265 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9267 *out_size
+= 2 * sizeof(DWORD
);
9268 }else if(vt
== VT_CARRAY
){
9269 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9270 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9272 }else if(vt
== VT_USERDEFINED
){
9273 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9274 encoded
[1] = desc
->u
.hreftype
;
9275 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9277 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9295 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9298 data
= file
->typdesc_seg
.data
;
9299 while(offs
< file
->typdesc_seg
.len
){
9300 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9302 offs
+= sizeof(encoded
);
9305 file
->typdesc_seg
.len
+= sizeof(encoded
);
9306 if(!file
->typdesc_seg
.data
)
9307 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9309 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9311 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9316 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9318 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9319 DWORD ret
= cdguids_seg
->len
, offs
;
9320 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
9323 if(list_empty(custdata_list
))
9326 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9327 if(!cdguids_seg
->data
){
9328 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9330 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9332 offs
= ret
+ sizeof(MSFT_CDGuid
);
9333 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9334 cdguid
->GuidOffset
= cd
->guid
->offset
;
9335 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9336 cdguid
->next
= offs
;
9337 offs
+= sizeof(MSFT_CDGuid
);
9347 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9348 WMSFT_TLBFile
*file
)
9350 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9351 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9352 MSFT_VarRecord
*varrecord
;
9353 MSFT_FuncRecord
*funcrecord
;
9355 DWORD
*name
, *offsets
, offs
;
9357 for(i
= 0; i
< info
->cFuncs
; ++i
){
9358 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9360 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9362 /* optional fields */
9363 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9364 if(!list_empty(&desc
->custdata_list
))
9365 recorded_size
+= 7 * sizeof(INT
);
9366 else if(desc
->HelpStringContext
!= 0)
9367 recorded_size
+= 6 * sizeof(INT
);
9369 else if(desc
->Entry
)
9370 recorded_size
+= 3 * sizeof(INT
);
9371 else if(desc
->HelpString
)
9372 recorded_size
+= 2 * sizeof(INT
);
9373 else if(desc
->helpcontext
)
9374 recorded_size
+= sizeof(INT
);
9376 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9378 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9379 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9380 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9385 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9388 for(i
= 0; i
< info
->cVars
; ++i
){
9389 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9391 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9393 /* optional fields */
9394 if(desc
->HelpStringContext
!= 0)
9395 recorded_size
+= 5 * sizeof(INT
);
9396 else if(!list_empty(&desc
->custdata_list
))
9397 recorded_size
+= 4 * sizeof(INT
);
9399 else if(desc
->HelpString
)
9400 recorded_size
+= 2 * sizeof(INT
);
9401 else if(desc
->HelpContext
!= 0)
9402 recorded_size
+= sizeof(INT
);
9404 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9407 if(!recorded_size
&& !extra_size
)
9410 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9412 aux_seg
->len
+= recorded_size
+ extra_size
;
9414 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9417 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9419 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9421 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9423 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9426 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9427 for(i
= 0; i
< info
->cFuncs
; ++i
){
9428 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9429 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9431 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9432 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9433 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9434 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9437 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9442 * ^has_param_defaults
9443 * ^oEntry_is_intresource
9445 funcrecord
->FKCCIC
=
9446 desc
->funcdesc
.funckind
|
9447 (desc
->funcdesc
.invkind
<< 3) |
9448 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9449 (desc
->funcdesc
.callconv
<< 8);
9451 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9452 funcrecord
->FKCCIC
|= 0x2000;
9454 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9455 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9456 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9457 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9460 if(paramdefault_size
> 0)
9461 funcrecord
->FKCCIC
|= 0x1000;
9463 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9464 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9466 /* optional fields */
9468 if(!list_empty(&desc
->custdata_list
)){
9469 size
+= 7 * sizeof(INT
);
9470 funcrecord
->HelpContext
= desc
->helpcontext
;
9471 if(desc
->HelpString
)
9472 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9474 funcrecord
->oHelpString
= -1;
9476 funcrecord
->oEntry
= -1;
9477 else if(IS_INTRESOURCE(desc
->Entry
))
9478 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9480 funcrecord
->oEntry
= desc
->Entry
->offset
;
9481 funcrecord
->res9
= -1;
9482 funcrecord
->resA
= -1;
9483 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9484 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9485 }else if(desc
->HelpStringContext
!= 0){
9486 size
+= 6 * sizeof(INT
);
9487 funcrecord
->HelpContext
= desc
->helpcontext
;
9488 if(desc
->HelpString
)
9489 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9491 funcrecord
->oHelpString
= -1;
9493 funcrecord
->oEntry
= -1;
9494 else if(IS_INTRESOURCE(desc
->Entry
))
9495 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9497 funcrecord
->oEntry
= desc
->Entry
->offset
;
9498 funcrecord
->res9
= -1;
9499 funcrecord
->resA
= -1;
9500 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9501 }else if(desc
->Entry
){
9502 size
+= 3 * sizeof(INT
);
9503 funcrecord
->HelpContext
= desc
->helpcontext
;
9504 if(desc
->HelpString
)
9505 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9507 funcrecord
->oHelpString
= -1;
9509 funcrecord
->oEntry
= -1;
9510 else if(IS_INTRESOURCE(desc
->Entry
))
9511 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9513 funcrecord
->oEntry
= desc
->Entry
->offset
;
9514 }else if(desc
->HelpString
){
9515 size
+= 2 * sizeof(INT
);
9516 funcrecord
->HelpContext
= desc
->helpcontext
;
9517 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9518 }else if(desc
->helpcontext
){
9519 size
+= sizeof(INT
);
9520 funcrecord
->HelpContext
= desc
->helpcontext
;
9523 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9524 size
+= paramdefault_size
;
9526 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9527 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9529 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9530 if(desc
->pParamDesc
[j
].Name
)
9531 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9534 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9536 if(paramdefault_size
){
9537 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9538 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9539 else if(paramdefault_size
)
9544 size
+= sizeof(MSFT_ParameterInfo
);
9547 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9553 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9556 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9557 for(i
= 0; i
< info
->cVars
; ++i
){
9558 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9559 DWORD size
= 5 * sizeof(INT
);
9561 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9562 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9563 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9564 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9566 if(desc
->vardesc
.varkind
== VAR_CONST
){
9567 varrecord
->vardescsize
+= sizeof(VARIANT
);
9568 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9570 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9573 if(desc
->HelpStringContext
!= 0){
9574 size
+= 5 * sizeof(INT
);
9575 varrecord
->HelpContext
= desc
->HelpContext
;
9576 if(desc
->HelpString
)
9577 varrecord
->HelpString
= desc
->HelpString
->offset
;
9579 varrecord
->HelpString
= -1;
9580 varrecord
->res9
= -1;
9581 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9582 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9583 }else if(!list_empty(&desc
->custdata_list
)){
9584 size
+= 4 * sizeof(INT
);
9585 varrecord
->HelpContext
= desc
->HelpContext
;
9586 if(desc
->HelpString
)
9587 varrecord
->HelpString
= desc
->HelpString
->offset
;
9589 varrecord
->HelpString
= -1;
9590 varrecord
->res9
= -1;
9591 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9592 }else if(desc
->HelpString
){
9593 size
+= 2 * sizeof(INT
);
9594 varrecord
->HelpContext
= desc
->HelpContext
;
9595 if(desc
->HelpString
)
9596 varrecord
->HelpString
= desc
->HelpString
->offset
;
9598 varrecord
->HelpString
= -1;
9599 }else if(desc
->HelpContext
!= 0){
9600 size
+= sizeof(INT
);
9601 varrecord
->HelpContext
= desc
->HelpContext
;
9604 varrecord
->Info
= size
| (i
<< 16);
9610 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9613 memid
= (MEMBERID
*)varrecord
;
9614 for(i
= 0; i
< info
->cFuncs
; ++i
){
9615 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9616 *memid
= desc
->funcdesc
.memid
;
9619 for(i
= 0; i
< info
->cVars
; ++i
){
9620 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9621 *memid
= desc
->vardesc
.memid
;
9625 name
= (UINT
*)memid
;
9626 for(i
= 0; i
< info
->cFuncs
; ++i
){
9627 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9629 *name
= desc
->Name
->offset
;
9634 for(i
= 0; i
< info
->cVars
; ++i
){
9635 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9637 *name
= desc
->Name
->offset
;
9646 typedef struct tagWMSFT_RefChunk
{
9653 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9655 DWORD offs
= file
->ref_seg
.len
, i
;
9656 WMSFT_RefChunk
*chunk
;
9658 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9659 if(!file
->ref_seg
.data
)
9660 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9662 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9664 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9666 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9667 chunk
->href
= info
->impltypes
[i
].hRef
;
9668 chunk
->res04
= info
->impltypes
[i
].implflags
;
9670 if(i
< info
->cImplTypes
- 1)
9671 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9680 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9684 size
= sizeof(MSFT_TypeInfoBase
);
9687 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9688 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9689 base
->typekind
= TKIND_DISPATCH
;
9691 base
->typekind
= info
->typekind
;
9692 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9693 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9694 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9699 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9705 base
->posguid
= info
->guid
->offset
;
9708 base
->flags
= info
->wTypeFlags
;
9710 base
->NameOffset
= info
->Name
->offset
;
9712 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9713 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9715 base
->NameOffset
= -1;
9717 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9719 base
->docstringoffs
= info
->DocString
->offset
;
9721 base
->docstringoffs
= -1;
9722 base
->helpstringcontext
= info
->dwHelpStringContext
;
9723 base
->helpcontext
= info
->dwHelpContext
;
9724 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9725 base
->cImplTypes
= info
->cImplTypes
;
9726 base
->cbSizeVft
= info
->cbSizeVft
;
9727 base
->size
= info
->cbSizeInstance
;
9728 if(info
->typekind
== TKIND_COCLASS
){
9729 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9730 }else if(info
->typekind
== TKIND_ALIAS
){
9731 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9732 }else if(info
->typekind
== TKIND_MODULE
){
9734 base
->datatype1
= info
->DllName
->offset
;
9736 base
->datatype1
= -1;
9738 if(info
->cImplTypes
> 0)
9739 base
->datatype1
= info
->impltypes
[0].hRef
;
9741 base
->datatype1
= -1;
9743 base
->datatype2
= index
; /* FIXME: i think there's more here */
9751 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9755 file
->typeinfo_seg
.len
= 0;
9756 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9757 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9758 *junk
= file
->typeinfo_seg
.len
;
9760 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9763 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9764 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9766 file
->aux_seg
.len
= 0;
9767 file
->aux_seg
.data
= NULL
;
9769 file
->typeinfo_seg
.len
= 0;
9770 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9771 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9772 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9773 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9777 typedef struct tagWMSFT_ImpFile
{
9783 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9786 WMSFT_ImpFile
*impfile
;
9788 DWORD last_offs
= 0;
9790 file
->impfile_seg
.len
= 0;
9791 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9795 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9799 path
= implib
->name
;
9800 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9802 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9805 size
+= sizeof(INT16
);
9807 size
= (size
+ 4) & ~0x3;
9811 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9814 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9816 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9817 int strlen
= 0, size
;
9819 impfile
= (WMSFT_ImpFile
*)data
;
9820 impfile
->guid_offs
= implib
->guid
->offset
;
9821 impfile
->lcid
= implib
->lcid
;
9822 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9824 data
+= sizeof(WMSFT_ImpFile
);
9827 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9831 path
= implib
->name
;
9832 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9833 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9835 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9838 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9840 size
= strlen
+ sizeof(INT16
);
9842 size
= (size
+ 4) & ~0x3;
9845 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9848 implib
->offset
= last_offs
;
9849 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9853 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9856 TLBRefType
*ref_type
;
9859 WMSFT_compile_impfile(This
, file
);
9861 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9862 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9864 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9865 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9866 if(ref_type
->index
== TLB_REF_USE_GUID
){
9867 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9868 info
->oGuid
= ref_type
->guid
->offset
;
9870 info
->oGuid
= ref_type
->index
;
9871 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9877 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9879 file
->guidhash_seg
.len
= 0x80;
9880 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9881 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9884 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9886 file
->namehash_seg
.len
= 0x200;
9887 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9888 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9891 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9893 if(contents
&& contents
->len
){
9894 segdir
->offset
= *running_offset
;
9895 segdir
->length
= contents
->len
;
9896 *running_offset
+= segdir
->length
;
9898 segdir
->offset
= -1;
9902 /* TODO: do these ever change? */
9904 segdir
->res0c
= 0xf;
9907 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9911 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9914 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9918 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9920 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9921 base
->memoffset
+= file_len
;
9928 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9930 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9931 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9932 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9933 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9934 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9935 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9936 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9937 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9938 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9939 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9940 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9941 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9942 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9943 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9946 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9948 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9950 DWORD written
, junk_size
, junk_offs
, running_offset
;
9957 TRACE("%p\n", This
);
9959 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
9960 if(This
->typeinfos
[i
]->needs_layout
)
9961 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
9963 memset(&file
, 0, sizeof(file
));
9965 file
.header
.magic1
= 0x5446534D;
9966 file
.header
.magic2
= 0x00010002;
9967 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9968 file
.header
.lcid2
= This
->set_lcid
;
9969 file
.header
.varflags
= 0x40 | This
->syskind
;
9971 file
.header
.varflags
|= 0x10;
9972 if (This
->HelpStringDll
)
9973 file
.header
.varflags
|= HELPDLLFLAG
;
9974 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
9975 file
.header
.flags
= This
->libflags
;
9976 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9977 file
.header
.helpcontext
= This
->dwHelpContext
;
9978 file
.header
.res44
= 0x20;
9979 file
.header
.res48
= 0x80;
9980 file
.header
.dispatchpos
= This
->dispatch_href
;
9982 WMSFT_compile_namehash(This
, &file
);
9983 /* do name and string compilation to get offsets for other compilations */
9984 hres
= WMSFT_compile_names(This
, &file
);
9986 WMSFT_free_file(&file
);
9990 hres
= WMSFT_compile_strings(This
, &file
);
9992 WMSFT_free_file(&file
);
9996 WMSFT_compile_guidhash(This
, &file
);
9997 hres
= WMSFT_compile_guids(This
, &file
);
9999 WMSFT_free_file(&file
);
10004 file
.header
.helpfile
= This
->HelpFile
->offset
;
10006 file
.header
.helpfile
= -1;
10008 if(This
->DocString
)
10009 file
.header
.helpstring
= This
->DocString
->offset
;
10011 file
.header
.helpstring
= -1;
10013 /* do some more segment compilation */
10014 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10015 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10018 file
.header
.NameOffset
= This
->Name
->offset
;
10020 file
.header
.NameOffset
= -1;
10022 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
10025 file
.header
.posguid
= This
->guid
->offset
;
10027 file
.header
.posguid
= -1;
10029 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10030 if(file
.header
.varflags
& HELPDLLFLAG
)
10031 junk_size
+= sizeof(DWORD
);
10033 junk
= heap_alloc_zero(junk_size
);
10034 if(file
.header
.varflags
& HELPDLLFLAG
){
10035 *junk
= This
->HelpStringDll
->offset
;
10044 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10045 WMSFT_compile_impinfo(This
, &file
);
10047 running_offset
= 0;
10049 TRACE("header at: 0x%x\n", running_offset
);
10050 running_offset
+= sizeof(file
.header
);
10052 TRACE("junk at: 0x%x\n", running_offset
);
10053 running_offset
+= junk_size
;
10055 TRACE("segdir at: 0x%x\n", running_offset
);
10056 running_offset
+= sizeof(file
.segdir
);
10058 TRACE("typeinfo at: 0x%x\n", running_offset
);
10059 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10061 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10062 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10064 TRACE("guidtab at: 0x%x\n", running_offset
);
10065 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10067 TRACE("reftab at: 0x%x\n", running_offset
);
10068 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10070 TRACE("impinfo at: 0x%x\n", running_offset
);
10071 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10073 TRACE("impfiles at: 0x%x\n", running_offset
);
10074 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10076 TRACE("namehashtab at: 0x%x\n", running_offset
);
10077 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10079 TRACE("nametab at: 0x%x\n", running_offset
);
10080 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10082 TRACE("stringtab at: 0x%x\n", running_offset
);
10083 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10085 TRACE("typdesc at: 0x%x\n", running_offset
);
10086 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10088 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10089 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10091 TRACE("custdata at: 0x%x\n", running_offset
);
10092 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10094 TRACE("cdguids at: 0x%x\n", running_offset
);
10095 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10097 TRACE("res0e at: 0x%x\n", running_offset
);
10098 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10100 TRACE("res0f at: 0x%x\n", running_offset
);
10101 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10103 TRACE("aux_seg at: 0x%x\n", running_offset
);
10105 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10107 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10108 FILE_ATTRIBUTE_NORMAL
, 0);
10109 if (outfile
== INVALID_HANDLE_VALUE
){
10110 WMSFT_free_file(&file
);
10112 return TYPE_E_IOERROR
;
10115 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10117 WMSFT_free_file(&file
);
10118 CloseHandle(outfile
);
10120 return TYPE_E_IOERROR
;
10123 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10126 WMSFT_free_file(&file
);
10127 CloseHandle(outfile
);
10128 return TYPE_E_IOERROR
;
10131 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10133 WMSFT_free_file(&file
);
10134 CloseHandle(outfile
);
10135 return TYPE_E_IOERROR
;
10138 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10139 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10140 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10141 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10142 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10143 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10144 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10145 WMSFT_write_segment(outfile
, &file
.name_seg
);
10146 WMSFT_write_segment(outfile
, &file
.string_seg
);
10147 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10148 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10149 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10150 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10151 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10153 WMSFT_free_file(&file
);
10155 CloseHandle(outfile
);
10160 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10163 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10164 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10168 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10169 REFGUID guid
, VARIANT
*varVal
)
10171 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10172 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
10176 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10177 ULONG helpStringContext
)
10179 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10180 FIXME("%p %u - stub\n", This
, helpStringContext
);
10184 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10187 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10188 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10191 return E_INVALIDARG
;
10193 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10198 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10199 ICreateTypeLib2_fnQueryInterface
,
10200 ICreateTypeLib2_fnAddRef
,
10201 ICreateTypeLib2_fnRelease
,
10202 ICreateTypeLib2_fnCreateTypeInfo
,
10203 ICreateTypeLib2_fnSetName
,
10204 ICreateTypeLib2_fnSetVersion
,
10205 ICreateTypeLib2_fnSetGuid
,
10206 ICreateTypeLib2_fnSetDocString
,
10207 ICreateTypeLib2_fnSetHelpFileName
,
10208 ICreateTypeLib2_fnSetHelpContext
,
10209 ICreateTypeLib2_fnSetLcid
,
10210 ICreateTypeLib2_fnSetLibFlags
,
10211 ICreateTypeLib2_fnSaveAllChanges
,
10212 ICreateTypeLib2_fnDeleteTypeInfo
,
10213 ICreateTypeLib2_fnSetCustData
,
10214 ICreateTypeLib2_fnSetHelpStringContext
,
10215 ICreateTypeLib2_fnSetHelpStringDll
10218 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10219 REFIID riid
, void **object
)
10221 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10223 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10226 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10228 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10230 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10233 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10235 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10237 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10240 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10243 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10245 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10247 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10252 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10255 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10259 TRACE("%p %x\n", This
, typeFlags
);
10261 if (typeFlags
& TYPEFLAG_FDUAL
) {
10262 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10264 ITypeInfo
*dispatch
;
10268 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10272 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10273 ITypeLib_Release(stdole
);
10277 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10278 ITypeInfo_Release(dispatch
);
10283 old_flags
= This
->wTypeFlags
;
10284 This
->wTypeFlags
= typeFlags
;
10286 hres
= ICreateTypeInfo2_LayOut(iface
);
10287 if (FAILED(hres
)) {
10288 This
->wTypeFlags
= old_flags
;
10295 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10298 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10300 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10303 return E_INVALIDARG
;
10305 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10310 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10313 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10315 TRACE("%p %d\n", This
, helpContext
);
10317 This
->dwHelpContext
= helpContext
;
10322 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10323 WORD majorVerNum
, WORD minorVerNum
)
10325 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10327 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10329 This
->wMajorVerNum
= majorVerNum
;
10330 This
->wMinorVerNum
= minorVerNum
;
10335 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10336 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10338 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10340 ITypeLib
*container
;
10341 TLBRefType
*ref_type
;
10343 TYPEATTR
*typeattr
;
10347 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10349 if (!typeInfo
|| !refType
)
10350 return E_INVALIDARG
;
10352 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10356 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10357 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10359 ITypeLib_Release(container
);
10361 *refType
= target
->hreftype
;
10366 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10367 if (FAILED(hres
)) {
10368 ITypeLib_Release(container
);
10372 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10373 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10374 implib
->lcid
== libattr
->lcid
&&
10375 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10376 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10380 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10381 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10383 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10384 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10385 implib
->name
= SysAllocString(our_container
->path
);
10387 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10388 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10390 implib
->name
= NULL
;
10391 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10395 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10396 implib
->lcid
= libattr
->lcid
;
10397 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10398 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10400 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10403 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10404 ITypeLib_Release(container
);
10406 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10411 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10412 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10413 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10414 ref_type
->tkind
== typeattr
->typekind
)
10419 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10420 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10422 ref_type
->tkind
= typeattr
->typekind
;
10423 ref_type
->pImpTLInfo
= implib
;
10424 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10426 ref_type
->index
= TLB_REF_USE_GUID
;
10428 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10430 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10433 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10435 *refType
= ref_type
->reference
| 0x1;
10437 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10438 This
->pTypeLib
->dispatch_href
= *refType
;
10443 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10444 UINT index
, FUNCDESC
*funcDesc
)
10446 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10447 TLBFuncDesc tmp_func_desc
, *func_desc
;
10452 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10454 if (!funcDesc
|| funcDesc
->oVft
& 3)
10455 return E_INVALIDARG
;
10457 switch (This
->typekind
) {
10459 if (funcDesc
->funckind
!= FUNC_STATIC
)
10460 return TYPE_E_BADMODULEKIND
;
10462 case TKIND_DISPATCH
:
10463 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10464 return TYPE_E_BADMODULEKIND
;
10467 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10468 return TYPE_E_BADMODULEKIND
;
10471 if (index
> This
->cFuncs
)
10472 return TYPE_E_ELEMENTNOTFOUND
;
10474 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10475 !funcDesc
->cParams
)
10476 return TYPE_E_INCONSISTENTPROPFUNCS
;
10479 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10480 funcDesc
->oVft
% 8 != 0)
10481 return E_INVALIDARG
;
10484 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10485 TLBFuncDesc_Constructor(&tmp_func_desc
);
10487 tmp_func_desc
.funcdesc
= *funcDesc
;
10489 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10490 tmp_func_desc
.funcdesc
.oVft
|= 1;
10492 if (funcDesc
->cScodes
) {
10493 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10494 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10496 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10498 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10499 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10500 buf_size
+= sizeof(ELEMDESC
);
10501 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10503 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10504 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10506 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10507 if (FAILED(hres
)) {
10508 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10509 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10513 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10514 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10515 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10516 if (FAILED(hres
)) {
10517 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10518 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10521 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10522 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10523 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10524 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10525 if (FAILED(hres
)) {
10526 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10527 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10533 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10535 if (This
->funcdescs
) {
10536 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10537 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10539 if (index
< This
->cFuncs
) {
10540 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10541 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10542 func_desc
= This
->funcdescs
+ index
;
10544 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10546 /* move custdata lists to the new memory location */
10547 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10549 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10550 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10551 list_init(&fd
->custdata_list
);
10553 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10554 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10559 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10561 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10562 list_init(&func_desc
->custdata_list
);
10566 This
->needs_layout
= TRUE
;
10571 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10572 UINT index
, HREFTYPE refType
)
10574 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10575 TLBImplType
*impl_type
;
10578 TRACE("%p %u %d\n", This
, index
, refType
);
10580 switch(This
->typekind
){
10581 case TKIND_COCLASS
: {
10583 FIXME("Unhandled index: -1\n");
10587 if(index
!= This
->cImplTypes
)
10588 return TYPE_E_ELEMENTNOTFOUND
;
10592 case TKIND_INTERFACE
:
10593 case TKIND_DISPATCH
:
10594 if (index
!= 0 || This
->cImplTypes
)
10595 return TYPE_E_ELEMENTNOTFOUND
;
10598 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10602 if (This
->impltypes
){
10605 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10606 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10608 if (index
< This
->cImplTypes
) {
10609 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10610 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10611 impl_type
= This
->impltypes
+ index
;
10613 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10615 /* move custdata lists to the new memory location */
10616 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10618 TLBImplType
*it
= &This
->impltypes
[i
];
10619 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10620 list_init(&it
->custdata_list
);
10622 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10623 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10628 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10630 memset(impl_type
, 0, sizeof(TLBImplType
));
10631 TLBImplType_Constructor(impl_type
);
10632 impl_type
->hRef
= refType
;
10634 ++This
->cImplTypes
;
10636 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10637 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10639 hres
= ICreateTypeInfo2_LayOut(iface
);
10646 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10647 UINT index
, INT implTypeFlags
)
10649 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10650 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10652 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10654 if (This
->typekind
!= TKIND_COCLASS
)
10655 return TYPE_E_BADMODULEKIND
;
10657 if (index
>= This
->cImplTypes
)
10658 return TYPE_E_ELEMENTNOTFOUND
;
10660 impl_type
->implflags
= implTypeFlags
;
10665 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10668 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10670 TRACE("%p %d\n", This
, alignment
);
10672 This
->cbAlignment
= alignment
;
10677 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10680 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10682 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10685 return E_INVALIDARG
;
10687 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10689 This
->lpstrSchema
= This
->Schema
->str
;
10694 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10695 UINT index
, VARDESC
*varDesc
)
10697 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10698 TLBVarDesc
*var_desc
;
10700 TRACE("%p %u %p\n", This
, index
, varDesc
);
10702 if (This
->vardescs
){
10705 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10706 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10708 if (index
< This
->cVars
) {
10709 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10710 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10711 var_desc
= This
->vardescs
+ index
;
10713 var_desc
= This
->vardescs
+ This
->cVars
;
10715 /* move custdata lists to the new memory location */
10716 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10718 TLBVarDesc
*var
= &This
->vardescs
[i
];
10719 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10720 list_init(&var
->custdata_list
);
10722 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10723 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10728 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10730 TLBVarDesc_Constructor(var_desc
);
10731 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10732 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10736 This
->needs_layout
= TRUE
;
10741 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10742 UINT index
, LPOLESTR
*names
, UINT numNames
)
10744 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10745 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10748 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10751 return E_INVALIDARG
;
10753 if (index
>= This
->cFuncs
|| numNames
== 0)
10754 return TYPE_E_ELEMENTNOTFOUND
;
10756 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10757 if(numNames
> func_desc
->funcdesc
.cParams
)
10758 return TYPE_E_ELEMENTNOTFOUND
;
10760 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10761 return TYPE_E_ELEMENTNOTFOUND
;
10763 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10764 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10765 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10766 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10767 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10768 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10770 return TYPE_E_AMBIGUOUSNAME
;
10774 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10776 for (i
= 1; i
< numNames
; ++i
) {
10777 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10778 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10784 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10785 UINT index
, LPOLESTR name
)
10787 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10789 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10792 return E_INVALIDARG
;
10794 if(index
>= This
->cVars
)
10795 return TYPE_E_ELEMENTNOTFOUND
;
10797 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10801 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10802 TYPEDESC
*tdescAlias
)
10804 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10807 TRACE("%p %p\n", This
, tdescAlias
);
10810 return E_INVALIDARG
;
10812 if(This
->typekind
!= TKIND_ALIAS
)
10813 return TYPE_E_BADMODULEKIND
;
10815 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->cbSizeInstance
, &This
->cbAlignment
);
10819 heap_free(This
->tdescAlias
);
10820 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10821 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10826 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10827 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10829 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10830 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10834 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10835 UINT index
, LPOLESTR docString
)
10837 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10838 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10840 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10843 return E_INVALIDARG
;
10845 if(index
>= This
->cFuncs
)
10846 return TYPE_E_ELEMENTNOTFOUND
;
10848 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10853 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10854 UINT index
, LPOLESTR docString
)
10856 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10857 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10859 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10862 return E_INVALIDARG
;
10864 if(index
>= This
->cVars
)
10865 return TYPE_E_ELEMENTNOTFOUND
;
10867 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10872 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10873 UINT index
, DWORD helpContext
)
10875 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10876 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10878 TRACE("%p %u %d\n", This
, index
, helpContext
);
10880 if(index
>= This
->cFuncs
)
10881 return TYPE_E_ELEMENTNOTFOUND
;
10883 func_desc
->helpcontext
= helpContext
;
10888 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10889 UINT index
, DWORD helpContext
)
10891 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10892 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10894 TRACE("%p %u %d\n", This
, index
, helpContext
);
10896 if(index
>= This
->cVars
)
10897 return TYPE_E_ELEMENTNOTFOUND
;
10899 var_desc
->HelpContext
= helpContext
;
10904 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10905 UINT index
, BSTR bstrMops
)
10907 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10908 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10912 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10915 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10917 TRACE("%p %p\n", This
, idlDesc
);
10920 return E_INVALIDARG
;
10922 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10923 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10928 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10930 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10932 TLBFuncDesc
*func_desc
;
10933 UINT user_vft
= 0, i
, depth
= 0;
10934 HRESULT hres
= S_OK
;
10936 TRACE("%p\n", This
);
10938 This
->needs_layout
= FALSE
;
10940 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10944 if (This
->typekind
== TKIND_INTERFACE
) {
10949 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10951 if (SUCCEEDED(hres
)) {
10952 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10954 if (SUCCEEDED(hres
)) {
10955 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10956 if (FAILED(hres
)) {
10957 ITypeInfo_Release(inh
);
10958 ITypeInfo_Release(tinfo
);
10961 This
->cbSizeVft
= attr
->cbSizeVft
;
10962 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10966 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10967 if(SUCCEEDED(hres
)){
10969 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10970 if(SUCCEEDED(hres
)){
10971 ITypeInfo_Release(inh
);
10975 }while(SUCCEEDED(hres
));
10978 ITypeInfo_Release(inh
);
10979 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10980 This
->cbSizeVft
= 0;
10983 ITypeInfo_Release(tinfo
);
10986 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10987 This
->cbSizeVft
= 0;
10990 ITypeInfo_Release(tinfo
);
10993 } else if (This
->typekind
== TKIND_DISPATCH
)
10994 This
->cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10996 This
->cbSizeVft
= 0;
10998 func_desc
= This
->funcdescs
;
11000 while (i
< This
->cFuncs
) {
11001 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11002 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
11004 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11005 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11007 This
->cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11009 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11012 BOOL reset
= FALSE
;
11014 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11016 iter
= This
->funcdescs
;
11017 while (j
< This
->cFuncs
) {
11018 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11020 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
11023 ++func_desc
->funcdesc
.memid
;
11024 iter
= This
->funcdescs
;
11037 if (user_vft
> This
->cbSizeVft
)
11038 This
->cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11040 for(i
= 0; i
< This
->cVars
; ++i
){
11041 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11042 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11044 BOOL reset
= FALSE
;
11047 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11049 iter
= This
->vardescs
;
11050 while (j
< This
->cVars
) {
11051 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11053 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->cVars
;
11056 ++var_desc
->vardesc
.memid
;
11057 iter
= This
->vardescs
;
11067 ITypeInfo_Release(tinfo
);
11071 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11074 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11075 FIXME("%p %u - stub\n", This
, index
);
11079 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11080 MEMBERID memid
, INVOKEKIND invKind
)
11082 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11083 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11087 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11090 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11091 FIXME("%p %u - stub\n", This
, index
);
11095 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11098 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11099 FIXME("%p %x - stub\n", This
, memid
);
11103 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11106 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11107 FIXME("%p %u - stub\n", This
, index
);
11111 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11112 REFGUID guid
, VARIANT
*varVal
)
11116 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11118 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11120 if (!guid
|| !varVal
)
11121 return E_INVALIDARG
;
11123 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11125 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11128 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11129 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11131 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11132 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11136 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11137 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11139 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11140 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11144 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11145 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11147 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11148 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11152 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11153 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11155 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11156 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11160 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11161 ULONG helpStringContext
)
11163 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11165 TRACE("%p %u\n", This
, helpStringContext
);
11167 This
->dwHelpStringContext
= helpStringContext
;
11172 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11173 UINT index
, ULONG helpStringContext
)
11175 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11176 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11180 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11181 UINT index
, ULONG helpStringContext
)
11183 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11184 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11188 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11190 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11191 FIXME("%p - stub\n", This
);
11195 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11198 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11200 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11203 return E_INVALIDARG
;
11205 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11210 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11211 ICreateTypeInfo2_fnQueryInterface
,
11212 ICreateTypeInfo2_fnAddRef
,
11213 ICreateTypeInfo2_fnRelease
,
11214 ICreateTypeInfo2_fnSetGuid
,
11215 ICreateTypeInfo2_fnSetTypeFlags
,
11216 ICreateTypeInfo2_fnSetDocString
,
11217 ICreateTypeInfo2_fnSetHelpContext
,
11218 ICreateTypeInfo2_fnSetVersion
,
11219 ICreateTypeInfo2_fnAddRefTypeInfo
,
11220 ICreateTypeInfo2_fnAddFuncDesc
,
11221 ICreateTypeInfo2_fnAddImplType
,
11222 ICreateTypeInfo2_fnSetImplTypeFlags
,
11223 ICreateTypeInfo2_fnSetAlignment
,
11224 ICreateTypeInfo2_fnSetSchema
,
11225 ICreateTypeInfo2_fnAddVarDesc
,
11226 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11227 ICreateTypeInfo2_fnSetVarName
,
11228 ICreateTypeInfo2_fnSetTypeDescAlias
,
11229 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11230 ICreateTypeInfo2_fnSetFuncDocString
,
11231 ICreateTypeInfo2_fnSetVarDocString
,
11232 ICreateTypeInfo2_fnSetFuncHelpContext
,
11233 ICreateTypeInfo2_fnSetVarHelpContext
,
11234 ICreateTypeInfo2_fnSetMops
,
11235 ICreateTypeInfo2_fnSetTypeIdldesc
,
11236 ICreateTypeInfo2_fnLayOut
,
11237 ICreateTypeInfo2_fnDeleteFuncDesc
,
11238 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11239 ICreateTypeInfo2_fnDeleteVarDesc
,
11240 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11241 ICreateTypeInfo2_fnDeleteImplType
,
11242 ICreateTypeInfo2_fnSetCustData
,
11243 ICreateTypeInfo2_fnSetFuncCustData
,
11244 ICreateTypeInfo2_fnSetParamCustData
,
11245 ICreateTypeInfo2_fnSetVarCustData
,
11246 ICreateTypeInfo2_fnSetImplTypeCustData
,
11247 ICreateTypeInfo2_fnSetHelpStringContext
,
11248 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11249 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11250 ICreateTypeInfo2_fnInvalidate
,
11251 ICreateTypeInfo2_fnSetName
11254 /******************************************************************************
11255 * ClearCustData (OLEAUT32.171)
11257 * Clear a custom data type's data.
11260 * lpCust [I] The custom data type instance
11265 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11267 if (lpCust
&& lpCust
->cCustData
)
11269 if (lpCust
->prgCustData
)
11273 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11274 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11276 CoTaskMemFree(lpCust
->prgCustData
);
11277 lpCust
->prgCustData
= NULL
;
11279 lpCust
->cCustData
= 0;