4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
46 * -. lousy fatal error handling
51 #include "wine/port.h"
60 #define NONAMELESSUNION
71 #include "wine/unicode.h"
74 #include "wine/debug.h"
76 #include "wine/list.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
79 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
93 WORD type_id
; /* Type identifier */
94 WORD count
; /* Number of resources of this type */
95 DWORD resloader
; /* SetResourceHandler() */
101 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
102 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
103 static void TLB_FreeVarDesc(VARDESC
*);
105 /****************************************************************************
108 * Takes p_iVal (which is in little endian) and returns it
109 * in the host machine's byte order.
111 #ifdef WORDS_BIGENDIAN
112 static WORD
FromLEWord(WORD p_iVal
)
114 return (((p_iVal
& 0x00FF) << 8) |
115 ((p_iVal
& 0xFF00) >> 8));
119 static DWORD
FromLEDWord(DWORD p_iVal
)
121 return (((p_iVal
& 0x000000FF) << 24) |
122 ((p_iVal
& 0x0000FF00) << 8) |
123 ((p_iVal
& 0x00FF0000) >> 8) |
124 ((p_iVal
& 0xFF000000) >> 24));
127 #define FromLEWord(X) (X)
128 #define FromLEDWord(X) (X)
131 #define DISPATCH_HREF_OFFSET 0x01000000
132 #define DISPATCH_HREF_MASK 0xff000000
134 /****************************************************************************
137 * Fix byte order in any structure if necessary
139 #ifdef WORDS_BIGENDIAN
140 static void FromLEWords(void *p_Val
, int p_iSize
)
144 p_iSize
/= sizeof(WORD
);
147 *Val
= FromLEWord(*Val
);
154 static void FromLEDWords(void *p_Val
, int p_iSize
)
158 p_iSize
/= sizeof(DWORD
);
161 *Val
= FromLEDWord(*Val
);
167 #define FromLEWords(X,Y) /*nothing*/
168 #define FromLEDWords(X,Y) /*nothing*/
172 * Find a typelib key which matches a requested maj.min version.
174 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
176 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
180 INT best_maj
= -1, best_min
= -1;
183 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
184 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
186 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
189 len
= sizeof(key_name
);
191 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
195 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
197 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
199 if (*wMaj
== 0xffff && *wMin
== 0xffff)
201 if (v_maj
> best_maj
) best_maj
= v_maj
;
202 if (v_min
> best_min
) best_min
= v_min
;
204 else if (*wMaj
== v_maj
)
211 break; /* exact match */
213 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
216 len
= sizeof(key_name
);
220 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
222 if (*wMaj
== 0xffff && *wMin
== 0xffff)
224 if (best_maj
>= 0 && best_min
>= 0)
232 if (*wMaj
== best_maj
&& best_min
>= 0)
240 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
241 /* buffer must be at least 60 characters long */
242 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
244 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
245 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
247 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
248 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
249 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
253 /* get the path of an interface key, in the form "Interface\\<guid>" */
254 /* buffer must be at least 50 characters long */
255 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
257 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
259 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
260 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
264 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
265 /* buffer must be at least 16 characters long */
266 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
268 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
269 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
270 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
271 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
273 sprintfW( buffer
, LcidFormatW
, lcid
);
276 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
277 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
278 case SYS_WIN64
: strcatW( buffer
, win64W
); break;
280 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
286 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
288 struct tlibredirect_data
302 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
303 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
304 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
306 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
310 WCHAR Path
[MAX_PATH
];
313 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
317 ACTCTX_SECTION_KEYED_DATA data
;
319 data
.cbSize
= sizeof(data
);
320 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
322 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
326 if (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
)
327 return TYPE_E_LIBNOTREGISTERED
;
329 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
330 len
= SearchPathW( NULL
, nameW
, NULL
, sizeof(Path
)/sizeof(WCHAR
), Path
, NULL
);
331 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
333 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
334 *path
= SysAllocString( Path
);
339 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
340 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
342 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
343 if (res
== ERROR_FILE_NOT_FOUND
)
345 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
346 return TYPE_E_LIBNOTREGISTERED
;
348 else if (res
!= ERROR_SUCCESS
)
350 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
351 return TYPE_E_REGISTRYACCESS
;
356 LONG dwPathLen
= sizeof(Path
);
358 get_lcid_subkey( myLCID
, syskind
, buffer
);
360 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
364 else if (myLCID
== lcid
)
366 /* try with sub-langid */
367 myLCID
= SUBLANGID(lcid
);
369 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
371 /* try with system langid */
381 *path
= SysAllocString( Path
);
386 TRACE_(typelib
)("-- 0x%08x\n", hr
);
390 /****************************************************************************
391 * QueryPathOfRegTypeLib [OLEAUT32.164]
393 * Gets the path to a registered type library.
396 * guid [I] referenced guid
397 * wMaj [I] major version
398 * wMin [I] minor version
400 * path [O] path of typelib
404 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
405 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
408 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
412 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
417 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
420 /******************************************************************************
421 * CreateTypeLib [OLEAUT32.160] creates a typelib
427 HRESULT WINAPI
CreateTypeLib(
428 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
430 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
434 /******************************************************************************
435 * LoadTypeLib [OLEAUT32.161]
437 * Loads a type library
440 * szFile [I] Name of file to load from.
441 * pptLib [O] Pointer that receives ITypeLib object on success.
448 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
450 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
452 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
453 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
456 /******************************************************************************
457 * LoadTypeLibEx [OLEAUT32.183]
459 * Loads and optionally registers a type library
465 HRESULT WINAPI
LoadTypeLibEx(
466 LPCOLESTR szFile
, /* [in] Name of file to load from */
467 REGKIND regkind
, /* [in] Specify kind of registration */
468 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
470 WCHAR szPath
[MAX_PATH
+1];
473 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
477 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
482 case REGKIND_DEFAULT
:
483 /* don't register typelibs supplied with full path. Experimentation confirms the following */
484 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
485 (szFile
[0] && (szFile
[1] == ':'))) break;
486 /* else fall-through */
488 case REGKIND_REGISTER
:
489 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
491 ITypeLib_Release(*pptLib
);
499 TRACE(" returns %08x\n",res
);
503 /******************************************************************************
504 * LoadRegTypeLib [OLEAUT32.162]
506 * Loads a registered type library.
509 * rguid [I] GUID of the registered type library.
510 * wVerMajor [I] major version.
511 * wVerMinor [I] minor version.
512 * lcid [I] locale ID.
513 * ppTLib [O] pointer that receives an ITypeLib object on success.
517 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
520 HRESULT WINAPI
LoadRegTypeLib(
532 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
536 res
= LoadTypeLib(bstr
, ppTLib
);
543 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
546 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
547 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
551 ITypeLib_Release(*ppTLib
);
553 res
= TYPE_E_LIBNOTREGISTERED
;
559 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
565 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
566 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
567 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
568 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
569 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
570 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
572 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
577 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
578 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
579 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
581 get_interface_key( &tattr
->guid
, keyName
);
582 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
583 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
586 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
587 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
589 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
590 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
591 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
592 (const BYTE
*)PSOA
, sizeof PSOA
);
596 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
597 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
598 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
599 (const BYTE
*)PSOA
, sizeof PSOA
);
603 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
604 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
607 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
608 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
610 StringFromGUID2(&libattr
->guid
, buffer
, 40);
611 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
612 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
613 sprintfW(buffer
, fmtver
, libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
614 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
615 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
623 /******************************************************************************
624 * RegisterTypeLib [OLEAUT32.163]
625 * Adds information about a type library to the System Registry
627 * Docs: ITypeLib FAR * ptlib
628 * Docs: OLECHAR FAR* szFullPath
629 * Docs: OLECHAR FAR* szHelpDir
635 HRESULT WINAPI
RegisterTypeLib(
636 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
637 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
638 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
650 if (ptlib
== NULL
|| szFullPath
== NULL
)
653 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
657 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
660 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
663 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
664 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
668 /* Set the human-readable name of the typelib */
669 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
673 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
674 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
680 /* Make up the name of the typelib path subkey */
681 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
683 /* Create the typelib path subkey */
684 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
685 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
687 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
688 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
696 /* Create the flags subkey */
697 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
698 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
700 /* FIXME: is %u correct? */
701 static const WCHAR formatW
[] = {'%','u',0};
703 sprintfW(buf
, formatW
, attr
->wLibFlags
);
704 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
705 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
713 /* create the helpdir subkey */
714 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
715 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
717 BOOL freeHelpDir
= FALSE
;
720 /* if we created a new key, and helpDir was null, set the helpdir
721 to the directory which contains the typelib. However,
722 if we just opened an existing key, we leave the helpdir alone */
723 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
724 szHelpDir
= SysAllocString(szFullPath
);
725 pIndexStr
= strrchrW(szHelpDir
, '\\');
732 /* if we have an szHelpDir, set it! */
733 if (szHelpDir
!= NULL
) {
734 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
735 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
741 if (freeHelpDir
) SysFreeString(szHelpDir
);
753 /* register OLE Automation-compatible interfaces for this typelib */
754 types
= ITypeLib_GetTypeInfoCount(ptlib
);
755 for (tidx
=0; tidx
<types
; tidx
++) {
756 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
757 LPOLESTR name
= NULL
;
758 ITypeInfo
*tinfo
= NULL
;
760 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
763 case TKIND_INTERFACE
:
764 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
765 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
769 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
770 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
774 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
779 TYPEATTR
*tattr
= NULL
;
780 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
783 TRACE_(typelib
)("guid=%s, flags=%04x (",
784 debugstr_guid(&tattr
->guid
),
787 if (TRACE_ON(typelib
)) {
788 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
808 /* Register all dispinterfaces (which includes dual interfaces) and
809 oleautomation interfaces */
810 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
811 kind
== TKIND_DISPATCH
)
814 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
816 /* register interface<->typelib coupling */
817 TLB_register_interface(attr
, name
, tattr
, 0);
819 /* register TLBs into the opposite registry view, too */
820 if(opposite
== KEY_WOW64_32KEY
||
821 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
822 TLB_register_interface(attr
, name
, tattr
, opposite
);
825 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
828 ITypeInfo_Release(tinfo
);
835 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
840 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
842 WCHAR subKeyName
[50];
845 /* the path to the type */
846 get_interface_key( guid
, subKeyName
);
848 /* Delete its bits */
849 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
852 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
853 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
854 RegDeleteKeyW(subKey
, TypeLibW
);
856 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
859 /******************************************************************************
860 * UnRegisterTypeLib [OLEAUT32.186]
861 * Removes information about a type library from the System Registry
868 HRESULT WINAPI
UnRegisterTypeLib(
869 REFGUID libid
, /* [in] Guid of the library */
870 WORD wVerMajor
, /* [in] major version */
871 WORD wVerMinor
, /* [in] minor version */
872 LCID lcid
, /* [in] locale id */
875 BSTR tlibPath
= NULL
;
878 WCHAR subKeyName
[50];
881 BOOL deleteOtherStuff
;
883 TYPEATTR
* typeAttr
= NULL
;
885 ITypeInfo
* typeInfo
= NULL
;
886 ITypeLib
* typeLib
= NULL
;
889 TRACE("(IID: %s)\n",debugstr_guid(libid
));
891 /* Create the path to the key */
892 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
894 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
896 TRACE("Unsupported syskind %i\n", syskind
);
897 result
= E_INVALIDARG
;
901 /* get the path to the typelib on disk */
902 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
903 result
= E_INVALIDARG
;
907 /* Try and open the key to the type library. */
908 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
909 result
= E_INVALIDARG
;
913 /* Try and load the type library */
914 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
915 result
= TYPE_E_INVALIDSTATE
;
919 /* remove any types registered with this typelib */
920 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
921 for (i
=0; i
<numTypes
; i
++) {
922 /* get the kind of type */
923 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
927 /* skip non-interfaces, and get type info for the type */
928 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
931 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
934 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
938 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
939 kind
== TKIND_DISPATCH
)
942 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
944 TLB_unregister_interface(&typeAttr
->guid
, 0);
946 /* unregister TLBs into the opposite registry view, too */
947 if(opposite
== KEY_WOW64_32KEY
||
948 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
949 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
954 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
956 if (typeInfo
) ITypeInfo_Release(typeInfo
);
960 /* Now, delete the type library path subkey */
961 get_lcid_subkey( lcid
, syskind
, subKeyName
);
962 RegDeleteKeyW(key
, subKeyName
);
963 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
964 RegDeleteKeyW(key
, subKeyName
);
966 /* check if there is anything besides the FLAGS/HELPDIR keys.
967 If there is, we don't delete them */
968 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
969 deleteOtherStuff
= TRUE
;
971 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
972 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
974 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
975 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
976 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
977 deleteOtherStuff
= FALSE
;
981 /* only delete the other parts of the key if we're absolutely sure */
982 if (deleteOtherStuff
) {
983 RegDeleteKeyW(key
, FLAGSW
);
984 RegDeleteKeyW(key
, HELPDIRW
);
988 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
989 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
990 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
994 SysFreeString(tlibPath
);
995 if (typeLib
) ITypeLib_Release(typeLib
);
996 if (key
) RegCloseKey(key
);
1000 /******************************************************************************
1001 * RegisterTypeLibForUser [OLEAUT32.442]
1002 * Adds information about a type library to the user registry
1004 * Docs: ITypeLib FAR * ptlib
1005 * Docs: OLECHAR FAR* szFullPath
1006 * Docs: OLECHAR FAR* szHelpDir
1012 HRESULT WINAPI
RegisterTypeLibForUser(
1013 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
1014 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
1015 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1018 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1019 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1020 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1023 /******************************************************************************
1024 * UnRegisterTypeLibForUser [OLEAUT32.443]
1025 * Removes information about a type library from the user registry
1031 HRESULT WINAPI
UnRegisterTypeLibForUser(
1032 REFGUID libid
, /* [in] GUID of the library */
1033 WORD wVerMajor
, /* [in] major version */
1034 WORD wVerMinor
, /* [in] minor version */
1035 LCID lcid
, /* [in] locale id */
1038 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1039 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1040 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1043 /*======================= ITypeLib implementation =======================*/
1045 typedef struct tagTLBGuid
{
1052 typedef struct tagTLBCustData
1059 /* data structure for import typelibs */
1060 typedef struct tagTLBImpLib
1062 int offset
; /* offset in the file (MSFT)
1063 offset in nametable (SLTG)
1064 just used to identify library while reading
1066 TLBGuid
*guid
; /* libid */
1067 BSTR name
; /* name */
1069 LCID lcid
; /* lcid of imported typelib */
1071 WORD wVersionMajor
; /* major version number */
1072 WORD wVersionMinor
; /* minor version number */
1074 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1075 NULL if not yet loaded */
1079 typedef struct tagTLBString
{
1085 /* internal ITypeLib data */
1086 typedef struct tagITypeLibImpl
1088 ITypeLib2 ITypeLib2_iface
;
1089 ITypeComp ITypeComp_iface
;
1090 ICreateTypeLib2 ICreateTypeLib2_iface
;
1101 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1102 * exported to the application as a UNICODE string.
1104 struct list string_list
;
1105 struct list name_list
;
1106 struct list guid_list
;
1108 const TLBString
*Name
;
1109 const TLBString
*DocString
;
1110 const TLBString
*HelpFile
;
1111 const TLBString
*HelpStringDll
;
1112 DWORD dwHelpContext
;
1113 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1114 struct tagITypeInfoImpl
**typeinfos
;
1115 struct list custdata_list
;
1116 struct list implib_list
;
1117 int ctTypeDesc
; /* number of items in type desc array */
1118 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1119 library. Only used while reading MSFT
1121 struct list ref_list
; /* list of ref types in this typelib */
1122 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1125 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1131 static const ITypeLib2Vtbl tlbvt
;
1132 static const ITypeCompVtbl tlbtcvt
;
1133 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1135 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1137 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1140 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1142 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1145 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1147 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1150 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1152 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1155 /* ITypeLib methods */
1156 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1157 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1159 /*======================= ITypeInfo implementation =======================*/
1161 /* data for referenced types */
1162 typedef struct tagTLBRefType
1164 INT index
; /* Type index for internal ref or for external ref
1165 it the format is SLTG. -2 indicates to
1169 TLBGuid
*guid
; /* guid of the referenced type */
1170 /* if index == TLB_REF_USE_GUID */
1172 HREFTYPE reference
; /* The href of this ref */
1173 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1174 TLB_REF_INTERNAL for internal refs
1175 TLB_REF_NOT_FOUND for broken refs */
1180 #define TLB_REF_USE_GUID -2
1182 #define TLB_REF_INTERNAL (void*)-2
1183 #define TLB_REF_NOT_FOUND (void*)-1
1185 /* internal Parameter data */
1186 typedef struct tagTLBParDesc
1188 const TLBString
*Name
;
1189 struct list custdata_list
;
1192 /* internal Function data */
1193 typedef struct tagTLBFuncDesc
1195 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1196 const TLBString
*Name
; /* the name of this function */
1197 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1199 int HelpStringContext
;
1200 const TLBString
*HelpString
;
1201 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1202 struct list custdata_list
;
1205 /* internal Variable data */
1206 typedef struct tagTLBVarDesc
1208 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1209 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1210 const TLBString
*Name
; /* the name of this variable */
1212 int HelpStringContext
;
1213 const TLBString
*HelpString
;
1214 struct list custdata_list
;
1217 /* internal implemented interface data */
1218 typedef struct tagTLBImplType
1220 HREFTYPE hRef
; /* hRef of interface */
1221 int implflags
; /* IMPLFLAG_*s */
1222 struct list custdata_list
;
1225 /* internal TypeInfo data */
1226 typedef struct tagITypeInfoImpl
1228 ITypeInfo2 ITypeInfo2_iface
;
1229 ITypeComp ITypeComp_iface
;
1230 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1232 BOOL not_attached_to_typelib
;
1237 MEMBERID memidConstructor
;
1238 MEMBERID memidDestructor
;
1239 LPOLESTR lpstrSchema
;
1240 ULONG cbSizeInstance
;
1250 TYPEDESC
*tdescAlias
;
1251 IDLDESC idldescType
;
1253 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1254 int index
; /* index in this typelib; */
1255 HREFTYPE hreftype
; /* hreftype for app object binding */
1256 /* type libs seem to store the doc strings in ascii
1257 * so why should we do it in unicode?
1259 const TLBString
*Name
;
1260 const TLBString
*DocString
;
1261 const TLBString
*DllName
;
1262 const TLBString
*Schema
;
1263 DWORD dwHelpContext
;
1264 DWORD dwHelpStringContext
;
1267 TLBFuncDesc
*funcdescs
;
1270 TLBVarDesc
*vardescs
;
1272 /* Implemented Interfaces */
1273 TLBImplType
*impltypes
;
1275 struct list
*pcustdata_list
;
1276 struct list custdata_list
;
1279 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1281 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1284 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1286 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1289 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1291 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1294 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1296 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1299 static const ITypeInfo2Vtbl tinfvt
;
1300 static const ITypeCompVtbl tcompvt
;
1301 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1303 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1304 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1306 typedef struct tagTLBContext
1308 unsigned int oStart
; /* start of TLB in file */
1309 unsigned int pos
; /* current pos */
1310 unsigned int length
; /* total length */
1311 void *mapping
; /* memory mapping */
1312 MSFT_SegDir
* pTblDir
;
1313 ITypeLibImpl
* pLibInfo
;
1317 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1319 return str
!= NULL
? str
->str
: NULL
;
1322 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1326 return memcmp(left
, str
->str
, len
);
1329 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1331 return guid
!= NULL
? &guid
->guid
: NULL
;
1334 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1336 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1339 static int get_ptr_size(SYSKIND syskind
)
1349 WARN("Unhandled syskind: 0x%x\n", syskind
);
1356 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1357 if (pTD
->vt
& VT_RESERVED
)
1358 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1359 if (pTD
->vt
& VT_BYREF
)
1360 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1361 if (pTD
->vt
& VT_ARRAY
)
1362 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1363 if (pTD
->vt
& VT_VECTOR
)
1364 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1365 switch(pTD
->vt
& VT_TYPEMASK
) {
1366 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1367 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1368 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1369 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1370 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1371 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1372 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1373 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1374 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1375 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1376 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1377 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1378 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1379 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1380 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1381 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1382 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1383 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1384 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1385 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1386 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1387 pTD
->u
.hreftype
); break;
1388 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1389 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1390 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1391 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1393 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1394 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1396 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1397 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1398 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1401 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1405 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1407 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1408 dump_TypeDesc(&edesc
->tdesc
,buf
);
1409 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1410 MESSAGE("\t\tu.paramdesc.wParamFlags");
1411 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1412 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1413 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1414 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1415 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1416 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1417 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1418 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1419 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1421 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1423 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1424 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1425 MESSAGE("Param %d:\n",i
);
1426 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1428 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1429 switch (funcdesc
->funckind
) {
1430 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1431 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1432 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1433 case FUNC_STATIC
: MESSAGE("static");break;
1434 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1435 default: MESSAGE("unknown");break;
1437 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1438 switch (funcdesc
->invkind
) {
1439 case INVOKE_FUNC
: MESSAGE("func");break;
1440 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1441 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1442 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1444 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1445 switch (funcdesc
->callconv
) {
1446 case CC_CDECL
: MESSAGE("cdecl");break;
1447 case CC_PASCAL
: MESSAGE("pascal");break;
1448 case CC_STDCALL
: MESSAGE("stdcall");break;
1449 case CC_SYSCALL
: MESSAGE("syscall");break;
1452 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1453 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1454 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1456 MESSAGE("\telemdescFunc (return value type):\n");
1457 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1460 static const char * const typekind_desc
[] =
1473 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1476 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1477 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1478 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1481 dump_FUNCDESC(&(pfd
->funcdesc
));
1483 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1484 if(pfd
->Entry
== NULL
)
1485 MESSAGE("\tentry: (null)\n");
1486 else if(pfd
->Entry
== (void*)-1)
1487 MESSAGE("\tentry: invalid\n");
1488 else if(IS_INTRESOURCE(pfd
->Entry
))
1489 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1491 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1493 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1497 dump_TLBFuncDescOne(pfd
);
1502 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1506 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1512 static void dump_TLBImpLib(const TLBImpLib
*import
)
1514 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1515 debugstr_w(import
->name
));
1516 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1517 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1520 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1524 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1526 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1527 if(ref
->index
== -1)
1528 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1530 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1532 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1534 TRACE_(typelib
)("in lib\n");
1535 dump_TLBImpLib(ref
->pImpTLInfo
);
1540 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1545 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1546 impl
->hRef
, impl
->implflags
);
1552 static void dump_DispParms(const DISPPARAMS
* pdp
)
1556 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1558 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1560 TRACE("named args:\n");
1561 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1562 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1565 if (pdp
->cArgs
&& pdp
->rgvarg
)
1568 for (index
= 0; index
< pdp
->cArgs
; index
++)
1569 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1573 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1575 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1576 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1577 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1578 TRACE("kind:%s\n", typekind_desc
[pty
->typekind
]);
1579 TRACE("fct:%u var:%u impl:%u\n", pty
->cFuncs
, pty
->cVars
, pty
->cImplTypes
);
1580 TRACE("wTypeFlags: 0x%04x\n", pty
->wTypeFlags
);
1581 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1582 if (pty
->typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1584 dump_TLBFuncDesc(pty
->funcdescs
, pty
->cFuncs
);
1585 dump_TLBVarDesc(pty
->vardescs
, pty
->cVars
);
1586 dump_TLBImplType(pty
->impltypes
, pty
->cImplTypes
);
1589 static void dump_VARDESC(const VARDESC
*v
)
1591 MESSAGE("memid %d\n",v
->memid
);
1592 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1593 MESSAGE("oInst %d\n",v
->u
.oInst
);
1594 dump_ELEMDESC(&(v
->elemdescVar
));
1595 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1596 MESSAGE("varkind %d\n",v
->varkind
);
1599 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1601 /* VT_LPWSTR is largest type that, may appear in type description */
1602 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1603 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1604 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1605 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1606 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1607 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1608 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1609 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1612 static void TLB_abort(void)
1617 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1619 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1620 if (!ret
) ERR("cannot allocate memory\n");
1624 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1626 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1627 if (!ret
) ERR("cannot allocate memory\n");
1631 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1633 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1636 void heap_free(void *ptr
)
1638 HeapFree(GetProcessHeap(), 0, ptr
);
1641 /* returns the size required for a deep copy of a typedesc into a
1643 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1647 if (alloc_initial_space
)
1648 size
+= sizeof(TYPEDESC
);
1654 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1657 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1658 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1664 /* deep copy a typedesc into a flat buffer */
1665 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1670 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1679 dest
->u
.lptdesc
= buffer
;
1680 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1683 dest
->u
.lpadesc
= buffer
;
1684 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1685 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1686 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1692 /* free custom data allocated by MSFT_CustData */
1693 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1695 TLBCustData
*cd
, *cdn
;
1696 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1698 list_remove(&cd
->entry
);
1699 VariantClear(&cd
->data
);
1704 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1709 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1710 ret
= SysAllocStringLen(NULL
, len
- 1);
1711 if (!ret
) return ret
;
1712 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1716 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1717 UINT n
, MEMBERID memid
)
1720 if(funcdescs
->funcdesc
.memid
== memid
)
1728 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1729 UINT n
, MEMBERID memid
)
1732 if(vardescs
->vardesc
.memid
== memid
)
1740 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1741 UINT n
, const OLECHAR
*name
)
1744 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1752 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1754 TLBCustData
*cust_data
;
1755 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1756 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1761 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1762 UINT n
, const OLECHAR
*name
)
1765 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1773 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1775 list_init(&var_desc
->custdata_list
);
1778 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1782 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1787 TLBVarDesc_Constructor(&ret
[n
-1]);
1794 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1798 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1803 list_init(&ret
[n
-1].custdata_list
);
1810 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1812 list_init(&func_desc
->custdata_list
);
1815 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1819 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1824 TLBFuncDesc_Constructor(&ret
[n
-1]);
1831 static void TLBImplType_Constructor(TLBImplType
*impl
)
1833 list_init(&impl
->custdata_list
);
1836 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1840 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1845 TLBImplType_Constructor(&ret
[n
-1]);
1852 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1853 const GUID
*new_guid
, HREFTYPE hreftype
)
1857 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1858 if (IsEqualGUID(&guid
->guid
, new_guid
))
1862 guid
= heap_alloc(sizeof(TLBGuid
));
1866 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1867 guid
->hreftype
= hreftype
;
1869 list_add_tail(guid_list
, &guid
->entry
);
1874 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1876 TLBCustData
*cust_data
;
1888 return DISP_E_BADVARTYPE
;
1891 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1894 cust_data
= heap_alloc(sizeof(TLBCustData
));
1896 return E_OUTOFMEMORY
;
1898 cust_data
->guid
= tlbguid
;
1899 VariantInit(&cust_data
->data
);
1901 list_add_tail(custdata_list
, &cust_data
->entry
);
1903 VariantClear(&cust_data
->data
);
1905 return VariantCopy(&cust_data
->data
, var
);
1908 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1915 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1916 if (strcmpW(str
->str
, new_str
) == 0)
1920 str
= heap_alloc(sizeof(TLBString
));
1924 str
->str
= SysAllocString(new_str
);
1930 list_add_tail(string_list
, &str
->entry
);
1935 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1936 ULONG
*size
, WORD
*align
)
1942 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1946 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1948 ITypeInfo_Release(other
);
1953 *size
= attr
->cbSizeInstance
;
1955 *align
= attr
->cbAlignment
;
1957 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1958 ITypeInfo_Release(other
);
1963 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1964 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1966 ULONG i
, sub
, ptr_size
;
1969 ptr_size
= get_ptr_size(sys
);
2008 *size
= sizeof(DATE
);
2011 *size
= sizeof(VARIANT
);
2013 if(sys
== SYS_WIN32
)
2014 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2018 *size
= sizeof(DECIMAL
);
2025 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2026 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2027 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2032 case VT_USERDEFINED
:
2033 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2035 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2049 /**********************************************************************
2051 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2054 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2056 if (where
!= DO_NOT_SEEK
)
2058 where
+= pcx
->oStart
;
2059 if (where
> pcx
->length
)
2062 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2070 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2072 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2073 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2075 MSFT_Seek(pcx
, where
);
2076 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2077 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2082 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2087 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2088 FromLEDWords(buffer
, ret
);
2093 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2098 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2099 FromLEWords(buffer
, ret
);
2104 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2107 MSFT_GuidEntry entry
;
2110 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2112 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2115 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2117 guid
= heap_alloc(sizeof(TLBGuid
));
2119 guid
->offset
= offs
;
2120 guid
->guid
= entry
.guid
;
2121 guid
->hreftype
= entry
.hreftype
;
2123 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2125 offs
+= sizeof(MSFT_GuidEntry
);
2129 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2133 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2134 if(ret
->offset
== offset
){
2135 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2143 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2145 MSFT_NameIntro niName
;
2149 ERR_(typelib
)("bad offset %d\n", offset
);
2153 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2154 pcx
->pTblDir
->pNametab
.offset
+offset
);
2156 return niName
.hreftype
;
2159 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2162 MSFT_NameIntro intro
;
2164 int offs
= 0, lengthInChars
;
2166 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2170 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2173 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2174 intro
.namelen
&= 0xFF;
2175 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2177 len_piece
= (len_piece
+ 4) & ~0x3;
2181 string
= heap_alloc(len_piece
+ 1);
2182 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2183 string
[intro
.namelen
] = '\0';
2185 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2186 string
, -1, NULL
, 0);
2187 if (!lengthInChars
) {
2189 return E_UNEXPECTED
;
2192 tlbstr
= heap_alloc(sizeof(TLBString
));
2194 tlbstr
->offset
= offs
;
2195 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2196 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2200 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2206 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2210 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2211 if (tlbstr
->offset
== offset
) {
2212 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2220 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2224 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2225 if (tlbstr
->offset
== offset
) {
2226 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2235 * read a value and fill a VARIANT structure
2237 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2241 TRACE_(typelib
)("\n");
2243 if(offset
<0) { /* data are packed in here */
2244 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2245 V_I4(pVar
) = offset
& 0x3ffffff;
2248 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2249 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2250 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2251 switch (V_VT(pVar
)){
2252 case VT_EMPTY
: /* FIXME: is this right? */
2253 case VT_NULL
: /* FIXME: is this right? */
2254 case VT_I2
: /* this should not happen */
2265 case VT_VOID
: /* FIXME: is this right? */
2273 case VT_DECIMAL
: /* FIXME: is this right? */
2276 /* pointer types with known behaviour */
2279 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2281 V_BSTR(pVar
) = NULL
;
2283 ptr
= heap_alloc_zero(size
);
2284 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2285 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2286 /* FIXME: do we need a AtoW conversion here? */
2287 V_UNION(pVar
, bstrVal
[size
])='\0';
2288 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2293 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2300 case VT_USERDEFINED
:
2306 case VT_STREAMED_OBJECT
:
2307 case VT_STORED_OBJECT
:
2308 case VT_BLOB_OBJECT
:
2313 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2317 if(size
>0) /* (big|small) endian correct? */
2318 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2322 * create a linked list with custom data
2324 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2330 TRACE_(typelib
)("\n");
2332 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2336 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2337 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2338 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2339 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2340 list_add_head(custdata_list
, &pNew
->entry
);
2341 offset
= entry
.next
;
2346 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2349 pTd
->vt
=type
& VT_TYPEMASK
;
2351 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2353 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2356 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2358 return (invkind
== INVOKE_PROPERTYGET
||
2359 invkind
== INVOKE_PROPERTYPUT
||
2360 invkind
== INVOKE_PROPERTYPUTREF
);
2364 MSFT_DoFuncs(TLBContext
* pcx
,
2369 TLBFuncDesc
** pptfd
)
2372 * member information is stored in a data structure at offset
2373 * indicated by the memoffset field of the typeinfo structure
2374 * There are several distinctive parts.
2375 * The first part starts with a field that holds the total length
2376 * of this (first) part excluding this field. Then follow the records,
2377 * for each member there is one record.
2379 * The first entry is always the length of the record (including this
2381 * The rest of the record depends on the type of the member. If there is
2382 * a field indicating the member type (function, variable, interface, etc)
2383 * I have not found it yet. At this time we depend on the information
2384 * in the type info and the usual order how things are stored.
2386 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2389 * Third is an equal sized array with file offsets to the name entry
2392 * The fourth and last (?) part is an array with offsets to the records
2393 * in the first part of this file segment.
2396 int infolen
, nameoffset
, reclength
, i
;
2397 int recoffset
= offset
+ sizeof(INT
);
2399 char *recbuf
= heap_alloc(0xffff);
2400 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2401 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2403 TRACE_(typelib
)("\n");
2405 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2407 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2409 for ( i
= 0; i
< cFuncs
; i
++ )
2413 /* name, eventually add to a hash table */
2414 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2415 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2417 /* read the function information record */
2418 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2420 reclength
&= 0xffff;
2422 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2424 /* size without argument data */
2425 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2426 if (pFuncRec
->FKCCIC
& 0x1000)
2427 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2429 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2430 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2432 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2433 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2435 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2437 if (pFuncRec
->FKCCIC
& 0x2000 )
2439 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2440 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2441 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2444 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2447 ptfd
->Entry
= (TLBString
*)-1;
2449 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2450 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2452 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2453 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2455 /* fill the FuncDesc Structure */
2456 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2457 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2459 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2460 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2461 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2462 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2463 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2464 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2465 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2467 /* nameoffset is sometimes -1 on the second half of a propget/propput
2468 * pair of functions */
2469 if ((nameoffset
== -1) && (i
> 0) &&
2470 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2471 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2472 ptfd
->Name
= ptfd_prev
->Name
;
2474 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2478 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2480 /* do the parameters/arguments */
2481 if(pFuncRec
->nrargs
)
2484 MSFT_ParameterInfo paraminfo
;
2486 ptfd
->funcdesc
.lprgelemdescParam
=
2487 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2489 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2491 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2492 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2494 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2496 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2502 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2505 if (paraminfo
.oName
!= -1)
2506 ptfd
->pParamDesc
[j
].Name
=
2507 MSFT_ReadName( pcx
, paraminfo
.oName
);
2508 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2511 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2512 (pFuncRec
->FKCCIC
& 0x1000) )
2514 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2516 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2518 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2520 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2521 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2523 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2527 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2530 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2531 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2532 pFuncRec
->FKCCIC
& 0x80 )
2535 pFuncRec
->oArgCustData
[j
],
2536 &ptfd
->pParamDesc
[j
].custdata_list
);
2539 /* SEEK value = jump to offset,
2540 * from there jump to the end of record,
2541 * go back by (j-1) arguments
2543 MSFT_ReadLEDWords( ¶minfo
,
2544 sizeof(MSFT_ParameterInfo
), pcx
,
2545 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2546 * sizeof(MSFT_ParameterInfo
)));
2550 /* scode is not used: archaic win16 stuff FIXME: right? */
2551 ptfd
->funcdesc
.cScodes
= 0 ;
2552 ptfd
->funcdesc
.lprgscode
= NULL
;
2556 recoffset
+= reclength
;
2561 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2562 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2564 int infolen
, nameoffset
, reclength
;
2566 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2571 TRACE_(typelib
)("\n");
2573 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2574 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2575 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2576 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2577 recoffset
+= offset
+sizeof(INT
);
2578 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2579 /* name, eventually add to a hash table */
2580 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2581 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2582 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2583 /* read the variable information record */
2584 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2586 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2589 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2590 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2592 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2593 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2595 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2596 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2598 /* fill the VarDesc Structure */
2599 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2600 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2601 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2602 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2603 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2604 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2605 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2606 if(pVarRec
->VarKind
== VAR_CONST
){
2607 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2608 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2609 pVarRec
->OffsValue
, pcx
);
2611 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2612 recoffset
+= reclength
;
2616 /* process Implemented Interfaces of a com class */
2617 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2621 MSFT_RefRecord refrec
;
2624 TRACE_(typelib
)("\n");
2626 pTI
->impltypes
= TLBImplType_Alloc(count
);
2627 pImpl
= pTI
->impltypes
;
2628 for(i
=0;i
<count
;i
++){
2629 if(offset
<0) break; /* paranoia */
2630 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2631 pImpl
->hRef
= refrec
.reftype
;
2632 pImpl
->implflags
=refrec
.flags
;
2633 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2634 offset
=refrec
.onext
;
2640 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2641 * and some structures, and fix the alignment */
2642 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2644 if(info
->typekind
== TKIND_ALIAS
){
2645 switch(info
->tdescAlias
->vt
){
2653 info
->cbSizeInstance
= sizeof(void*);
2654 info
->cbAlignment
= sizeof(void*);
2657 case VT_USERDEFINED
:
2658 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->cbSizeInstance
, &info
->cbAlignment
);
2661 info
->cbSizeInstance
= sizeof(VARIANT
);
2662 info
->cbAlignment
= 8;
2664 if(info
->cbSizeInstance
< sizeof(void*))
2665 info
->cbAlignment
= info
->cbSizeInstance
;
2667 info
->cbAlignment
= sizeof(void*);
2670 }else if(info
->typekind
== TKIND_INTERFACE
||
2671 info
->typekind
== TKIND_DISPATCH
||
2672 info
->typekind
== TKIND_COCLASS
){
2673 info
->cbSizeInstance
= sizeof(void*);
2674 info
->cbAlignment
= sizeof(void*);
2680 * process a typeinfo record
2682 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2685 ITypeLibImpl
* pLibInfo
)
2687 MSFT_TypeInfoBase tiBase
;
2688 ITypeInfoImpl
*ptiRet
;
2690 TRACE_(typelib
)("count=%u\n", count
);
2692 ptiRet
= ITypeInfoImpl_Constructor();
2693 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2694 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2696 /* this is where we are coming from */
2697 ptiRet
->pTypeLib
= pLibInfo
;
2698 ptiRet
->index
=count
;
2700 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2701 ptiRet
->lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2702 ptiRet
->lpstrSchema
=NULL
; /* reserved */
2703 ptiRet
->cbSizeInstance
=tiBase
.size
;
2704 ptiRet
->typekind
=tiBase
.typekind
& 0xF;
2705 ptiRet
->cFuncs
=LOWORD(tiBase
.cElement
);
2706 ptiRet
->cVars
=HIWORD(tiBase
.cElement
);
2707 ptiRet
->cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2708 ptiRet
->wTypeFlags
=tiBase
.flags
;
2709 ptiRet
->wMajorVerNum
=LOWORD(tiBase
.version
);
2710 ptiRet
->wMinorVerNum
=HIWORD(tiBase
.version
);
2711 ptiRet
->cImplTypes
=tiBase
.cImplTypes
;
2712 ptiRet
->cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2713 if(ptiRet
->typekind
== TKIND_ALIAS
){
2715 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2716 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2717 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2721 /* IDLDESC idldescType; *//* never saw this one != zero */
2723 /* name, eventually add to a hash table */
2724 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2725 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2726 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2728 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2729 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2730 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2732 if (ptiRet
->typekind
== TKIND_MODULE
)
2733 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2735 /* note: InfoType's Help file and HelpStringDll come from the containing
2736 * library. Further HelpString and Docstring appear to be the same thing :(
2739 if(ptiRet
->cFuncs
>0 )
2740 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->cFuncs
,
2742 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2744 if(ptiRet
->cVars
>0 )
2745 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->cFuncs
,
2747 tiBase
.memoffset
, &ptiRet
->vardescs
);
2748 if(ptiRet
->cImplTypes
>0 ) {
2749 switch(ptiRet
->typekind
)
2752 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->cImplTypes
,
2755 case TKIND_DISPATCH
:
2756 /* This is not -1 when the interface is a non-base dual interface or
2757 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2758 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2762 if (tiBase
.datatype1
!= -1)
2764 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2765 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2769 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2770 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2774 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2776 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2777 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2778 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2779 typekind_desc
[ptiRet
->typekind
]);
2780 if (TRACE_ON(typelib
))
2781 dump_TypeInfo(ptiRet
);
2786 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2789 INT16 len_str
, len_piece
;
2790 int offs
= 0, lengthInChars
;
2792 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2796 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2799 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2800 len_piece
= len_str
+ sizeof(INT16
);
2802 len_piece
= (len_piece
+ 4) & ~0x3;
2806 string
= heap_alloc(len_piece
+ 1);
2807 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2808 string
[len_str
] = '\0';
2810 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2811 string
, -1, NULL
, 0);
2812 if (!lengthInChars
) {
2814 return E_UNEXPECTED
;
2817 tlbstr
= heap_alloc(sizeof(TLBString
));
2819 tlbstr
->offset
= offs
;
2820 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2821 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2825 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2831 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2836 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2837 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2838 MSFT_ImpInfo impinfo
;
2841 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2843 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2844 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2846 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2847 if(pImpLib
->offset
==impinfo
.oImpFile
)
2850 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2851 ref
->reference
= offs
;
2852 ref
->pImpTLInfo
= pImpLib
;
2853 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2854 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2855 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2856 ref
->index
= TLB_REF_USE_GUID
;
2858 ref
->index
= impinfo
.oGuid
;
2860 ERR("Cannot find a reference\n");
2861 ref
->reference
= -1;
2862 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2865 offs
+= sizeof(impinfo
);
2871 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2872 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2873 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2876 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2877 static CRITICAL_SECTION cache_section
;
2878 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2880 0, 0, &cache_section
,
2881 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2882 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2884 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2887 typedef struct TLB_PEFile
2889 IUnknown IUnknown_iface
;
2892 HRSRC typelib_resource
;
2893 HGLOBAL typelib_global
;
2894 LPVOID typelib_base
;
2897 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2899 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2902 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2904 if (IsEqualIID(riid
, &IID_IUnknown
))
2907 IUnknown_AddRef(iface
);
2911 return E_NOINTERFACE
;
2914 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2916 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2917 return InterlockedIncrement(&This
->refs
);
2920 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2922 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2923 ULONG refs
= InterlockedDecrement(&This
->refs
);
2926 if (This
->typelib_global
)
2927 FreeResource(This
->typelib_global
);
2929 FreeLibrary(This
->dll
);
2935 static const IUnknownVtbl TLB_PEFile_Vtable
=
2937 TLB_PEFile_QueryInterface
,
2942 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2945 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2947 This
= heap_alloc(sizeof(TLB_PEFile
));
2949 return E_OUTOFMEMORY
;
2951 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2954 This
->typelib_resource
= NULL
;
2955 This
->typelib_global
= NULL
;
2956 This
->typelib_base
= NULL
;
2958 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2959 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2963 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2964 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2965 if (This
->typelib_resource
)
2967 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2968 if (This
->typelib_global
)
2970 This
->typelib_base
= LockResource(This
->typelib_global
);
2972 if (This
->typelib_base
)
2974 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2975 *ppBase
= This
->typelib_base
;
2976 *ppFile
= &This
->IUnknown_iface
;
2982 TRACE("No TYPELIB resource found\n");
2986 TLB_PEFile_Release(&This
->IUnknown_iface
);
2990 typedef struct TLB_NEFile
2992 IUnknown IUnknown_iface
;
2994 LPVOID typelib_base
;
2997 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2999 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
3002 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3004 if (IsEqualIID(riid
, &IID_IUnknown
))
3007 IUnknown_AddRef(iface
);
3011 return E_NOINTERFACE
;
3014 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
3016 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3017 return InterlockedIncrement(&This
->refs
);
3020 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
3022 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3023 ULONG refs
= InterlockedDecrement(&This
->refs
);
3026 heap_free(This
->typelib_base
);
3032 static const IUnknownVtbl TLB_NEFile_Vtable
=
3034 TLB_NEFile_QueryInterface
,
3039 /***********************************************************************
3040 * read_xx_header [internal]
3042 static int read_xx_header( HFILE lzfd
)
3044 IMAGE_DOS_HEADER mzh
;
3047 LZSeek( lzfd
, 0, SEEK_SET
);
3048 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3050 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3053 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3054 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3057 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3059 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3060 return IMAGE_OS2_SIGNATURE
;
3061 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3062 return IMAGE_NT_SIGNATURE
;
3065 WARN("Can't handle %s files.\n", magic
);
3070 /***********************************************************************
3071 * find_ne_resource [internal]
3073 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3074 DWORD
*resLen
, DWORD
*resOff
)
3076 IMAGE_OS2_HEADER nehd
;
3077 NE_TYPEINFO
*typeInfo
;
3078 NE_NAMEINFO
*nameInfo
;
3084 /* Read in NE header */
3085 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3086 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3088 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3091 TRACE("No resources in NE dll\n" );
3095 /* Read in resource table */
3096 resTab
= heap_alloc( resTabSize
);
3097 if ( !resTab
) return FALSE
;
3099 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3100 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3102 heap_free( resTab
);
3107 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3109 if (!IS_INTRESOURCE(typeid)) /* named type */
3111 BYTE len
= strlen( typeid );
3112 while (typeInfo
->type_id
)
3114 if (!(typeInfo
->type_id
& 0x8000))
3116 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3117 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
3119 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3120 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3123 else /* numeric type id */
3125 WORD id
= LOWORD(typeid) | 0x8000;
3126 while (typeInfo
->type_id
)
3128 if (typeInfo
->type_id
== id
) goto found_type
;
3129 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3130 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3133 TRACE("No typeid entry found for %p\n", typeid );
3134 heap_free( resTab
);
3138 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3140 if (!IS_INTRESOURCE(resid
)) /* named resource */
3142 BYTE len
= strlen( resid
);
3143 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3145 BYTE
*p
= resTab
+ nameInfo
->id
;
3146 if (nameInfo
->id
& 0x8000) continue;
3147 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3150 else /* numeric resource id */
3152 WORD id
= LOWORD(resid
) | 0x8000;
3153 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3154 if (nameInfo
->id
== id
) goto found_name
;
3156 TRACE("No resid entry found for %p\n", typeid );
3157 heap_free( resTab
);
3161 /* Return resource data */
3162 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3163 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3165 heap_free( resTab
);
3169 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3173 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3176 This
= heap_alloc(sizeof(TLB_NEFile
));
3177 if (!This
) return E_OUTOFMEMORY
;
3179 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3181 This
->typelib_base
= NULL
;
3183 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3184 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3186 DWORD reslen
, offset
;
3187 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3189 This
->typelib_base
= heap_alloc(reslen
);
3190 if( !This
->typelib_base
)
3194 LZSeek( lzfd
, offset
, SEEK_SET
);
3195 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3197 *ppBase
= This
->typelib_base
;
3198 *pdwTLBLength
= reslen
;
3199 *ppFile
= &This
->IUnknown_iface
;
3205 if( lzfd
>= 0) LZClose( lzfd
);
3206 TLB_NEFile_Release(&This
->IUnknown_iface
);
3210 typedef struct TLB_Mapping
3212 IUnknown IUnknown_iface
;
3216 LPVOID typelib_base
;
3219 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3221 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3224 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3226 if (IsEqualIID(riid
, &IID_IUnknown
))
3229 IUnknown_AddRef(iface
);
3233 return E_NOINTERFACE
;
3236 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3238 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3239 return InterlockedIncrement(&This
->refs
);
3242 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3244 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3245 ULONG refs
= InterlockedDecrement(&This
->refs
);
3248 if (This
->typelib_base
)
3249 UnmapViewOfFile(This
->typelib_base
);
3251 CloseHandle(This
->mapping
);
3252 if (This
->file
!= INVALID_HANDLE_VALUE
)
3253 CloseHandle(This
->file
);
3259 static const IUnknownVtbl TLB_Mapping_Vtable
=
3261 TLB_Mapping_QueryInterface
,
3266 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3270 This
= heap_alloc(sizeof(TLB_Mapping
));
3272 return E_OUTOFMEMORY
;
3274 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3276 This
->file
= INVALID_HANDLE_VALUE
;
3277 This
->mapping
= NULL
;
3278 This
->typelib_base
= NULL
;
3280 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3281 if (INVALID_HANDLE_VALUE
!= This
->file
)
3283 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3286 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3287 if(This
->typelib_base
)
3289 /* retrieve file size */
3290 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3291 *ppBase
= This
->typelib_base
;
3292 *ppFile
= &This
->IUnknown_iface
;
3298 IUnknown_Release(&This
->IUnknown_iface
);
3299 return TYPE_E_CANTLOADLIBRARY
;
3302 /****************************************************************************
3305 * find the type of the typelib file and map the typelib resource into
3309 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3310 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3312 ITypeLibImpl
*entry
;
3315 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3316 LPVOID pBase
= NULL
;
3317 DWORD dwTLBLength
= 0;
3318 IUnknown
*pFile
= NULL
;
3323 index_str
= strrchrW(pszFileName
, '\\');
3324 if(index_str
&& *++index_str
!= '\0')
3327 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3328 if(*end_ptr
== '\0')
3330 int str_len
= index_str
- pszFileName
- 1;
3332 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3333 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3338 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3340 if(strchrW(file
, '\\'))
3342 lstrcpyW(pszPath
, file
);
3346 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3347 pszPath
[len
] = '\\';
3348 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3352 if(file
!= pszFileName
) heap_free(file
);
3354 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3355 if(h
!= INVALID_HANDLE_VALUE
){
3356 FILE_NAME_INFORMATION size_info
;
3359 /* GetFileInformationByHandleEx returns the path of the file without
3360 * WOW64 redirection */
3361 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, &size_info
, sizeof(size_info
));
3362 if(br
|| GetLastError() == ERROR_MORE_DATA
){
3363 FILE_NAME_INFORMATION
*info
;
3364 DWORD size
= sizeof(*info
) + size_info
.FileNameLength
+ sizeof(WCHAR
);
3366 info
= HeapAlloc(GetProcessHeap(), 0, size
);
3368 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, info
, size
);
3370 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3371 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3374 HeapFree(GetProcessHeap(), 0, info
);
3380 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3382 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3383 EnterCriticalSection(&cache_section
);
3384 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3386 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3388 TRACE("cache hit\n");
3389 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3390 ITypeLib2_AddRef(*ppTypeLib
);
3391 LeaveCriticalSection(&cache_section
);
3395 LeaveCriticalSection(&cache_section
);
3397 /* now actually load and parse the typelib */
3399 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3400 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3401 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3402 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3403 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3406 if (dwTLBLength
>= 4)
3408 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3409 if (dwSignature
== MSFT_SIGNATURE
)
3410 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3411 else if (dwSignature
== SLTG_SIGNATURE
)
3412 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3415 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3416 ret
= TYPE_E_CANTLOADLIBRARY
;
3420 ret
= TYPE_E_CANTLOADLIBRARY
;
3421 IUnknown_Release(pFile
);
3425 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3427 TRACE("adding to cache\n");
3428 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3429 lstrcpyW(impl
->path
, pszPath
);
3430 /* We should really canonicalise the path here. */
3431 impl
->index
= index
;
3433 /* FIXME: check if it has added already in the meantime */
3434 EnterCriticalSection(&cache_section
);
3435 list_add_head(&tlb_cache
, &impl
->entry
);
3436 LeaveCriticalSection(&cache_section
);
3442 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3444 ret
= TYPE_E_CANTLOADLIBRARY
;
3451 /*================== ITypeLib(2) Methods ===================================*/
3453 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3455 ITypeLibImpl
* pTypeLibImpl
;
3457 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3458 if (!pTypeLibImpl
) return NULL
;
3460 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3461 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3462 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3463 pTypeLibImpl
->ref
= 1;
3465 list_init(&pTypeLibImpl
->implib_list
);
3466 list_init(&pTypeLibImpl
->custdata_list
);
3467 list_init(&pTypeLibImpl
->name_list
);
3468 list_init(&pTypeLibImpl
->string_list
);
3469 list_init(&pTypeLibImpl
->guid_list
);
3470 list_init(&pTypeLibImpl
->ref_list
);
3471 pTypeLibImpl
->dispatch_href
= -1;
3473 return pTypeLibImpl
;
3476 /****************************************************************************
3477 * ITypeLib2_Constructor_MSFT
3479 * loading an MSFT typelib from an in-memory image
3481 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3485 MSFT_Header tlbHeader
;
3486 MSFT_SegDir tlbSegDir
;
3487 ITypeLibImpl
* pTypeLibImpl
;
3490 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3492 pTypeLibImpl
= TypeLibImpl_Constructor();
3493 if (!pTypeLibImpl
) return NULL
;
3495 /* get pointer to beginning of typelib data */
3499 cx
.pLibInfo
= pTypeLibImpl
;
3500 cx
.length
= dwTLBLength
;
3503 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3504 TRACE_(typelib
)("header:\n");
3505 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3506 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3507 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3510 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3512 /* there is a small amount of information here until the next important
3514 * the segment directory . Try to calculate the amount of data */
3515 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3517 /* now read the segment directory */
3518 TRACE("read segment directory (at %d)\n",lPSegDir
);
3519 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3520 cx
.pTblDir
= &tlbSegDir
;
3522 /* just check two entries */
3523 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3525 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3526 heap_free(pTypeLibImpl
);
3530 MSFT_ReadAllNames(&cx
);
3531 MSFT_ReadAllStrings(&cx
);
3532 MSFT_ReadAllGuids(&cx
);
3534 /* now fill our internal data */
3535 /* TLIBATTR fields */
3536 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3538 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3539 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3540 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3541 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3542 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3544 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3545 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3547 /* name, eventually add to a hash table */
3548 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3551 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3552 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3554 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3557 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3558 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3561 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3564 if(tlbHeader
.CustomDataOffset
>= 0)
3566 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3569 /* fill in type descriptions */
3570 if(tlbSegDir
.pTypdescTab
.length
> 0)
3572 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3574 pTypeLibImpl
->ctTypeDesc
= cTD
;
3575 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3576 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3579 /* FIXME: add several sanity checks here */
3580 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3581 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3583 /* FIXME: check safearray */
3585 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3587 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3589 else if(td
[0] == VT_CARRAY
)
3591 /* array descr table here */
3592 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3594 else if(td
[0] == VT_USERDEFINED
)
3596 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3598 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3601 /* second time around to fill the array subscript info */
3604 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3605 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3607 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3608 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3611 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3613 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3615 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3617 for(j
= 0; j
<td
[2]; j
++)
3619 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3620 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3621 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3622 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3627 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3628 ERR("didn't find array description data\n");
3633 /* imported type libs */
3634 if(tlbSegDir
.pImpFiles
.offset
>0)
3637 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3640 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3644 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3645 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3646 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3648 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3649 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3650 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3651 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3654 name
= heap_alloc_zero(size
+1);
3655 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3656 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3659 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3660 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3662 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3666 MSFT_ReadAllRefs(&cx
);
3668 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3671 if(tlbHeader
.nrtypeinfos
>= 0 )
3673 ITypeInfoImpl
**ppTI
;
3675 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3677 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3679 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3682 (pTypeLibImpl
->TypeInfoCount
)++;
3687 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3688 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3689 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3693 TRACE("(%p)\n", pTypeLibImpl
);
3694 return &pTypeLibImpl
->ITypeLib2_iface
;
3698 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3704 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3705 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3709 guid
->Data4
[0] = s
>> 8;
3710 guid
->Data4
[1] = s
& 0xff;
3713 for(i
= 0; i
< 6; i
++) {
3714 memcpy(b
, str
+ 24 + 2 * i
, 2);
3715 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3720 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3727 bytelen
= *(const WORD
*)ptr
;
3728 if(bytelen
== 0xffff) return 2;
3730 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3731 tmp_str
= SysAllocStringLen(NULL
, len
);
3733 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3734 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3735 SysFreeString(tmp_str
);
3740 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3745 bytelen
= *(const WORD
*)ptr
;
3746 if(bytelen
== 0xffff) return 2;
3747 *str
= heap_alloc(bytelen
+ 1);
3748 memcpy(*str
, ptr
+ 2, bytelen
);
3749 (*str
)[bytelen
] = '\0';
3753 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3758 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3759 if (tlbstr
->offset
== offset
)
3763 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3764 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3765 SysFreeString(tmp_str
);
3770 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3772 char *ptr
= pLibBlk
;
3775 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3776 FIXME("libblk magic = %04x\n", w
);
3781 if((w
= *(WORD
*)ptr
) != 0xffff) {
3782 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3787 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3789 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3791 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3794 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3795 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3798 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3799 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3801 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3804 ptr
+= 4; /* skip res12 */
3806 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3809 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3812 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3815 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3816 ptr
+= sizeof(GUID
);
3818 return ptr
- (char*)pLibBlk
;
3821 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3826 } sltg_ref_lookup_t
;
3828 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3829 HREFTYPE
*typelib_ref
)
3831 if(table
&& typeinfo_ref
< table
->num
)
3833 *typelib_ref
= table
->refs
[typeinfo_ref
];
3837 ERR_(typelib
)("Unable to find reference\n");
3842 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3847 if((*pType
& 0xe00) == 0xe00) {
3849 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3850 pTD
= pTD
->u
.lptdesc
;
3852 switch(*pType
& 0x3f) {
3855 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3856 pTD
= pTD
->u
.lptdesc
;
3859 case VT_USERDEFINED
:
3860 pTD
->vt
= VT_USERDEFINED
;
3861 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3867 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3870 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3872 pTD
->vt
= VT_CARRAY
;
3873 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3874 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3875 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3876 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3878 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3884 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3888 pTD
->vt
= VT_SAFEARRAY
;
3889 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3890 pTD
= pTD
->u
.lptdesc
;
3894 pTD
->vt
= *pType
& 0x3f;
3903 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3904 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3906 /* Handle [in/out] first */
3907 if((*pType
& 0xc000) == 0xc000)
3908 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3909 else if(*pType
& 0x8000)
3910 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3911 else if(*pType
& 0x4000)
3912 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3914 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3917 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3920 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3922 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3926 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3931 TLBRefType
*ref_type
;
3932 sltg_ref_lookup_t
*table
;
3933 HREFTYPE typelib_ref
;
3935 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3936 FIXME("Ref magic = %x\n", pRef
->magic
);
3939 name
= ( (char*)pRef
->names
+ pRef
->number
);
3941 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3942 table
->num
= pRef
->number
>> 3;
3944 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3946 /* We don't want the first href to be 0 */
3947 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3949 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3951 unsigned int lib_offs
, type_num
;
3953 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3955 name
+= SLTG_ReadStringA(name
, &refname
);
3956 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3957 FIXME_(typelib
)("Can't sscanf ref\n");
3958 if(lib_offs
!= 0xffff) {
3961 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3962 if(import
->offset
== lib_offs
)
3965 if(&import
->entry
== &pTL
->implib_list
) {
3966 char fname
[MAX_PATH
+1];
3970 import
= heap_alloc_zero(sizeof(*import
));
3971 import
->offset
= lib_offs
;
3972 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3973 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3974 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3975 &import
->wVersionMajor
,
3976 &import
->wVersionMinor
,
3977 &import
->lcid
, fname
) != 4) {
3978 FIXME_(typelib
)("can't sscanf ref %s\n",
3979 pNameTable
+ lib_offs
+ 40);
3981 len
= strlen(fname
);
3982 if(fname
[len
-1] != '#')
3983 FIXME("fname = %s\n", fname
);
3984 fname
[len
-1] = '\0';
3985 import
->name
= TLB_MultiByteToBSTR(fname
);
3986 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3988 ref_type
->pImpTLInfo
= import
;
3990 /* Store a reference to IDispatch */
3991 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3992 pTL
->dispatch_href
= typelib_ref
;
3994 } else { /* internal ref */
3995 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3997 ref_type
->reference
= typelib_ref
;
3998 ref_type
->index
= type_num
;
4001 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
4003 table
->refs
[ref
] = typelib_ref
;
4006 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
4007 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
4008 dump_TLBRefType(pTL
);
4012 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
4013 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
4015 SLTG_ImplInfo
*info
;
4016 TLBImplType
*pImplType
;
4017 /* I don't really get this structure, usually it's 0x16 bytes
4018 long, but iuser.tlb contains some that are 0x18 bytes long.
4019 That's ok because we can use the next ptr to jump to the next
4020 one. But how do we know the length of the last one? The WORD
4021 at offs 0x8 might be the clue. For now I'm just assuming that
4022 the last one is the regular 0x16 bytes. */
4024 info
= (SLTG_ImplInfo
*)pBlk
;
4027 if(info
->next
== 0xffff)
4029 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4032 info
= (SLTG_ImplInfo
*)pBlk
;
4033 pTI
->impltypes
= TLBImplType_Alloc(pTI
->cImplTypes
);
4034 pImplType
= pTI
->impltypes
;
4036 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4037 pImplType
->implflags
= info
->impltypeflags
;
4040 if(info
->next
== 0xffff)
4043 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4044 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4046 info
++; /* see comment at top of function */
4050 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4051 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4053 TLBVarDesc
*pVarDesc
;
4054 const TLBString
*prevName
= NULL
;
4055 SLTG_Variable
*pItem
;
4059 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4061 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4062 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4064 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4066 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4067 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4068 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4072 if (pItem
->name
== 0xfffe)
4073 pVarDesc
->Name
= prevName
;
4075 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4077 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4078 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4079 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4081 if(pItem
->flags
& 0x02)
4082 pType
= &pItem
->type
;
4084 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4086 if (pItem
->flags
& ~0xda)
4087 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4089 SLTG_DoElem(pType
, pBlk
,
4090 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4092 if (TRACE_ON(typelib
)) {
4094 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4095 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4098 if (pItem
->flags
& 0x40) {
4099 TRACE_(typelib
)("VAR_DISPATCH\n");
4100 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4102 else if (pItem
->flags
& 0x10) {
4103 TRACE_(typelib
)("VAR_CONST\n");
4104 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4105 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4106 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4107 if (pItem
->flags
& 0x08)
4108 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4110 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4116 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4118 TRACE_(typelib
)("len = %u\n", len
);
4119 if (len
== 0xffff) {
4122 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4123 str
= SysAllocStringLen(NULL
, alloc_len
);
4124 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4126 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4127 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4136 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4137 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4140 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4145 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4146 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4147 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4150 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4151 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4153 if (pItem
->flags
& 0x80)
4154 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4156 prevName
= pVarDesc
->Name
;
4161 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4162 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4164 SLTG_Function
*pFunc
;
4166 TLBFuncDesc
*pFuncDesc
;
4168 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4170 pFuncDesc
= pTI
->funcdescs
;
4171 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4172 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4177 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4178 case SLTG_FUNCTION_MAGIC
:
4179 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4181 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4182 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4184 case SLTG_STATIC_FUNCTION_MAGIC
:
4185 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4188 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4191 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4193 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4194 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4195 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4196 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4197 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4198 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4200 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4201 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4203 if(pFunc
->retnextopt
& 0x80)
4204 pType
= &pFunc
->rettype
;
4206 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4208 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4210 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4211 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4212 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4214 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4216 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4217 char *paramName
= pNameTable
+ *pArg
;
4219 /* If arg type follows then paramName points to the 2nd
4220 letter of the name, else the next WORD is an offset to
4221 the arg type and paramName points to the first letter.
4222 So let's take one char off paramName and see if we're
4223 pointing at an alpha-numeric char. However if *pArg is
4224 0xffff or 0xfffe then the param has no name, the former
4225 meaning that the next WORD is the type, the latter
4226 meaning that the next WORD is an offset to the type. */
4231 else if(*pArg
== 0xfffe) {
4235 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4240 if(HaveOffs
) { /* the next word is an offset to type */
4241 pType
= (WORD
*)(pBlk
+ *pArg
);
4242 SLTG_DoElem(pType
, pBlk
,
4243 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4248 pArg
= SLTG_DoElem(pArg
, pBlk
,
4249 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4252 /* Are we an optional param ? */
4253 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4254 pFuncDesc
->funcdesc
.cParamsOpt
)
4255 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4258 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4259 paramName
- pNameTable
, pTI
->pTypeLib
);
4261 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4265 pTI
->cFuncs
= cFuncs
;
4268 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4269 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4270 SLTG_TypeInfoTail
*pTITail
)
4273 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4275 if(pTIHeader
->href_table
!= 0xffffffff) {
4276 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4282 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4283 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4285 heap_free(ref_lookup
);
4289 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4290 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4291 const SLTG_TypeInfoTail
*pTITail
)
4294 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4296 if(pTIHeader
->href_table
!= 0xffffffff) {
4297 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4303 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4304 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4307 if (pTITail
->funcs_off
!= 0xffff)
4308 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4310 heap_free(ref_lookup
);
4312 if (TRACE_ON(typelib
))
4313 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4316 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4317 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4318 const SLTG_TypeInfoTail
*pTITail
)
4320 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4323 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4324 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4325 const SLTG_TypeInfoTail
*pTITail
)
4328 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4330 if (pTITail
->simple_alias
) {
4331 /* if simple alias, no more processing required */
4332 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4333 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4337 if(pTIHeader
->href_table
!= 0xffffffff) {
4338 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4342 /* otherwise it is an offset to a type */
4343 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4345 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4346 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4348 heap_free(ref_lookup
);
4351 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4352 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4353 const SLTG_TypeInfoTail
*pTITail
)
4355 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4356 if (pTIHeader
->href_table
!= 0xffffffff)
4357 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4360 if (pTITail
->vars_off
!= 0xffff)
4361 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4363 if (pTITail
->funcs_off
!= 0xffff)
4364 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4366 if (pTITail
->impls_off
!= 0xffff)
4367 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4369 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4370 * of dispinterface functions including the IDispatch ones, so
4371 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4372 pTI
->cbSizeVft
= pTI
->cFuncs
* pTI
->pTypeLib
->ptr_size
;
4374 heap_free(ref_lookup
);
4375 if (TRACE_ON(typelib
))
4376 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4379 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4380 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4381 const SLTG_TypeInfoTail
*pTITail
)
4383 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4386 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4387 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4388 const SLTG_TypeInfoTail
*pTITail
)
4390 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4391 if (pTIHeader
->href_table
!= 0xffffffff)
4392 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4395 if (pTITail
->vars_off
!= 0xffff)
4396 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4398 if (pTITail
->funcs_off
!= 0xffff)
4399 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4400 heap_free(ref_lookup
);
4401 if (TRACE_ON(typelib
))
4405 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4406 manageable copy of it into this */
4419 } SLTG_InternalOtherTypeInfo
;
4421 /****************************************************************************
4422 * ITypeLib2_Constructor_SLTG
4424 * loading a SLTG typelib from an in-memory image
4426 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4428 ITypeLibImpl
*pTypeLibImpl
;
4429 SLTG_Header
*pHeader
;
4430 SLTG_BlkEntry
*pBlkEntry
;
4434 LPVOID pBlk
, pFirstBlk
;
4435 SLTG_LibBlk
*pLibBlk
;
4436 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4437 char *pAfterOTIBlks
= NULL
;
4438 char *pNameTable
, *ptr
;
4441 ITypeInfoImpl
**ppTypeInfoImpl
;
4443 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4446 pTypeLibImpl
= TypeLibImpl_Constructor();
4447 if (!pTypeLibImpl
) return NULL
;
4451 TRACE_(typelib
)("header:\n");
4452 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4453 pHeader
->nrOfFileBlks
);
4454 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4455 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4456 pHeader
->SLTG_magic
);
4460 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4461 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4463 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4464 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4466 /* Next we have a magic block */
4467 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4469 /* Let's see if we're still in sync */
4470 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4471 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4472 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4475 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4476 sizeof(SLTG_DIR_MAGIC
))) {
4477 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4481 pIndex
= (SLTG_Index
*)(pMagic
+1);
4483 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4485 pFirstBlk
= pPad9
+ 1;
4487 /* We'll set up a ptr to the main library block, which is the last one. */
4489 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4490 pBlkEntry
[order
].next
!= 0;
4491 order
= pBlkEntry
[order
].next
- 1, i
++) {
4492 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4496 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4498 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4503 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4505 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4508 ptr
= (char*)pLibBlk
+ len
;
4510 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4514 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4516 w
= *(WORD
*)(ptr
+ 2);
4519 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4520 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4521 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4523 w
= *(WORD
*)(ptr
+ 4 + len
);
4525 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4527 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4528 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4529 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4531 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4532 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4533 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4535 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4536 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4539 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4540 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4541 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4542 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4543 len
+= sizeof(SLTG_OtherTypeInfo
);
4547 pAfterOTIBlks
= ptr
;
4549 /* Skip this WORD and get the next DWORD */
4550 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4552 /* Now add this to pLibBLk look at what we're pointing at and
4553 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4554 dust and we should be pointing at the beginning of the name
4557 pNameTable
= (char*)pLibBlk
+ len
;
4559 switch(*(WORD
*)pNameTable
) {
4566 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4570 pNameTable
+= 0x216;
4574 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4576 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4579 /* Hopefully we now have enough ptrs set up to actually read in
4580 some TypeInfos. It's not clear which order to do them in, so
4581 I'll just follow the links along the BlkEntry chain and read
4582 them in the order in which they are in the file */
4584 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4585 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4587 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4588 pBlkEntry
[order
].next
!= 0;
4589 order
= pBlkEntry
[order
].next
- 1, i
++) {
4591 SLTG_TypeInfoHeader
*pTIHeader
;
4592 SLTG_TypeInfoTail
*pTITail
;
4593 SLTG_MemberHeader
*pMemHeader
;
4595 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4596 FIXME_(typelib
)("Index strings don't match\n");
4597 heap_free(pOtherTypeInfoBlks
);
4602 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4603 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4604 heap_free(pOtherTypeInfoBlks
);
4607 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4608 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4609 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4611 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4612 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4613 (*ppTypeInfoImpl
)->index
= i
;
4614 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4615 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4616 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4617 (*ppTypeInfoImpl
)->typekind
= pTIHeader
->typekind
;
4618 (*ppTypeInfoImpl
)->wMajorVerNum
= pTIHeader
->major_version
;
4619 (*ppTypeInfoImpl
)->wMinorVerNum
= pTIHeader
->minor_version
;
4620 (*ppTypeInfoImpl
)->wTypeFlags
=
4621 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4623 if((*ppTypeInfoImpl
)->wTypeFlags
& TYPEFLAG_FDUAL
)
4624 (*ppTypeInfoImpl
)->typekind
= TKIND_DISPATCH
;
4626 if((pTIHeader
->typeflags1
& 7) != 2)
4627 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4628 if(pTIHeader
->typeflags3
!= 2)
4629 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4631 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4632 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4633 typekind_desc
[pTIHeader
->typekind
],
4634 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4635 (*ppTypeInfoImpl
)->wTypeFlags
);
4637 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4639 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4641 (*ppTypeInfoImpl
)->cbAlignment
= pTITail
->cbAlignment
;
4642 (*ppTypeInfoImpl
)->cbSizeInstance
= pTITail
->cbSizeInstance
;
4643 (*ppTypeInfoImpl
)->cbSizeVft
= pTITail
->cbSizeVft
;
4645 switch(pTIHeader
->typekind
) {
4647 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4648 pTIHeader
, pTITail
);
4652 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4653 pTIHeader
, pTITail
);
4656 case TKIND_INTERFACE
:
4657 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4658 pTIHeader
, pTITail
);
4662 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4663 pTIHeader
, pTITail
);
4667 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4668 pTIHeader
, pTITail
);
4671 case TKIND_DISPATCH
:
4672 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4673 pTIHeader
, pTITail
);
4677 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4678 pTIHeader
, pTITail
);
4682 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4687 /* could get cFuncs, cVars and cImplTypes from here
4688 but we've already set those */
4689 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4705 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4708 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4709 FIXME("Somehow processed %d TypeInfos\n", i
);
4710 heap_free(pOtherTypeInfoBlks
);
4714 heap_free(pOtherTypeInfoBlks
);
4715 return &pTypeLibImpl
->ITypeLib2_iface
;
4718 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4720 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4722 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4724 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4725 IsEqualIID(riid
,&IID_ITypeLib
)||
4726 IsEqualIID(riid
,&IID_ITypeLib2
))
4728 *ppv
= &This
->ITypeLib2_iface
;
4730 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4731 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4733 *ppv
= &This
->ICreateTypeLib2_iface
;
4738 TRACE("-- Interface: E_NOINTERFACE\n");
4739 return E_NOINTERFACE
;
4742 IUnknown_AddRef((IUnknown
*)*ppv
);
4746 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4748 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4749 ULONG ref
= InterlockedIncrement(&This
->ref
);
4751 TRACE("(%p) ref=%u\n", This
, ref
);
4756 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4758 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4759 ULONG ref
= InterlockedDecrement(&This
->ref
);
4761 TRACE("(%p) ref=%u\n",This
, ref
);
4765 TLBImpLib
*pImpLib
, *pImpLibNext
;
4766 TLBRefType
*ref_type
;
4767 TLBString
*tlbstr
, *tlbstr_next
;
4768 TLBGuid
*tlbguid
, *tlbguid_next
;
4772 /* remove cache entry */
4775 TRACE("removing from cache list\n");
4776 EnterCriticalSection(&cache_section
);
4777 if(This
->entry
.next
)
4778 list_remove(&This
->entry
);
4779 LeaveCriticalSection(&cache_section
);
4780 heap_free(This
->path
);
4782 TRACE(" destroying ITypeLib(%p)\n",This
);
4784 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4785 list_remove(&tlbstr
->entry
);
4786 SysFreeString(tlbstr
->str
);
4790 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4791 list_remove(&tlbstr
->entry
);
4792 SysFreeString(tlbstr
->str
);
4796 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4797 list_remove(&tlbguid
->entry
);
4801 TLB_FreeCustData(&This
->custdata_list
);
4803 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4804 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4805 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4807 heap_free(This
->pTypeDesc
);
4809 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4811 if (pImpLib
->pImpTypeLib
)
4812 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4813 SysFreeString(pImpLib
->name
);
4815 list_remove(&pImpLib
->entry
);
4819 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4821 list_remove(&ref_type
->entry
);
4822 heap_free(ref_type
);
4825 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4826 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4827 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4829 heap_free(This
->typeinfos
);
4837 /* ITypeLib::GetTypeInfoCount
4839 * Returns the number of type descriptions in the type library
4841 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4843 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4844 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4845 return This
->TypeInfoCount
;
4848 /* ITypeLib::GetTypeInfo
4850 * retrieves the specified type description in the library.
4852 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4855 ITypeInfo
**ppTInfo
)
4857 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4859 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4862 return E_INVALIDARG
;
4864 if(index
>= This
->TypeInfoCount
)
4865 return TYPE_E_ELEMENTNOTFOUND
;
4867 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4868 ITypeInfo_AddRef(*ppTInfo
);
4874 /* ITypeLibs::GetTypeInfoType
4876 * Retrieves the type of a type description.
4878 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4883 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4885 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4888 return E_INVALIDARG
;
4890 if(index
>= This
->TypeInfoCount
)
4891 return TYPE_E_ELEMENTNOTFOUND
;
4893 *pTKind
= This
->typeinfos
[index
]->typekind
;
4898 /* ITypeLib::GetTypeInfoOfGuid
4900 * Retrieves the type description that corresponds to the specified GUID.
4903 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4906 ITypeInfo
**ppTInfo
)
4908 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4911 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4913 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4914 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4915 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4916 ITypeInfo_AddRef(*ppTInfo
);
4921 return TYPE_E_ELEMENTNOTFOUND
;
4924 /* ITypeLib::GetLibAttr
4926 * Retrieves the structure that contains the library's attributes.
4929 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4933 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4935 TRACE("(%p, %p)\n", This
, attr
);
4937 if (!attr
) return E_INVALIDARG
;
4939 *attr
= heap_alloc(sizeof(**attr
));
4940 if (!*attr
) return E_OUTOFMEMORY
;
4942 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4943 (*attr
)->lcid
= This
->set_lcid
;
4944 (*attr
)->syskind
= This
->syskind
;
4945 (*attr
)->wMajorVerNum
= This
->ver_major
;
4946 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4947 (*attr
)->wLibFlags
= This
->libflags
;
4952 /* ITypeLib::GetTypeComp
4954 * Enables a client compiler to bind to a library's types, variables,
4955 * constants, and global functions.
4958 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4960 ITypeComp
**ppTComp
)
4962 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4964 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4965 *ppTComp
= &This
->ITypeComp_iface
;
4966 ITypeComp_AddRef(*ppTComp
);
4971 /* ITypeLib::GetDocumentation
4973 * Retrieves the library's documentation string, the complete Help file name
4974 * and path, and the context identifier for the library Help topic in the Help
4977 * On a successful return all non-null BSTR pointers will have been set,
4980 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4984 BSTR
*pBstrDocString
,
4985 DWORD
*pdwHelpContext
,
4986 BSTR
*pBstrHelpFile
)
4988 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4989 HRESULT result
= E_INVALIDARG
;
4992 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4994 pBstrName
, pBstrDocString
,
4995 pdwHelpContext
, pBstrHelpFile
);
4999 /* documentation for the typelib */
5004 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
5012 if (This
->DocString
)
5014 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
5018 *pBstrDocString
= NULL
;
5022 *pdwHelpContext
= This
->dwHelpContext
;
5028 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5032 *pBstrHelpFile
= NULL
;
5039 /* for a typeinfo */
5040 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5042 if(SUCCEEDED(result
))
5044 result
= ITypeInfo_GetDocumentation(pTInfo
,
5048 pdwHelpContext
, pBstrHelpFile
);
5050 ITypeInfo_Release(pTInfo
);
5055 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5057 if (pBstrName
) SysFreeString (*pBstrName
);
5059 return STG_E_INSUFFICIENTMEMORY
;
5064 * Indicates whether a passed-in string contains the name of a type or member
5065 * described in the library.
5068 static HRESULT WINAPI
ITypeLib2_fnIsName(
5074 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5076 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5078 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5082 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5083 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5084 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5085 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5086 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5088 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5089 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5090 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5091 goto ITypeLib2_fnIsName_exit
;
5094 for(vrc
= 0; vrc
< pTInfo
->cVars
; ++vrc
){
5095 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5096 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5102 ITypeLib2_fnIsName_exit
:
5103 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5104 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5109 /* ITypeLib::FindName
5111 * Finds occurrences of a type description in a type library. This may be used
5112 * to quickly verify that a name exists in a type library.
5115 static HRESULT WINAPI
ITypeLib2_fnFindName(
5119 ITypeInfo
**ppTInfo
,
5123 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5128 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5130 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5131 return E_INVALIDARG
;
5133 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5134 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5135 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5139 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5140 memid
[count
] = MEMBERID_NIL
;
5141 goto ITypeLib2_fnFindName_exit
;
5144 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5145 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5147 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5148 memid
[count
] = func
->funcdesc
.memid
;
5149 goto ITypeLib2_fnFindName_exit
;
5153 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->cVars
, name
);
5155 memid
[count
] = var
->vardesc
.memid
;
5156 goto ITypeLib2_fnFindName_exit
;
5160 ITypeLib2_fnFindName_exit
:
5161 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5162 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5165 TRACE("found %d typeinfos\n", count
);
5172 /* ITypeLib::ReleaseTLibAttr
5174 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5177 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5179 TLIBATTR
*pTLibAttr
)
5181 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5182 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5183 heap_free(pTLibAttr
);
5186 /* ITypeLib2::GetCustData
5188 * gets the custom data
5190 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5195 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5196 TLBCustData
*pCData
;
5198 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5200 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5202 return TYPE_E_ELEMENTNOTFOUND
;
5204 VariantInit(pVarVal
);
5205 VariantCopy(pVarVal
, &pCData
->data
);
5210 /* ITypeLib2::GetLibStatistics
5212 * Returns statistics about a type library that are required for efficient
5213 * sizing of hash tables.
5216 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5218 ULONG
*pcUniqueNames
,
5219 ULONG
*pcchUniqueNames
)
5221 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5223 FIXME("(%p): stub!\n", This
);
5225 if(pcUniqueNames
) *pcUniqueNames
=1;
5226 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5230 /* ITypeLib2::GetDocumentation2
5232 * Retrieves the library's documentation string, the complete Help file name
5233 * and path, the localization context to use, and the context ID for the
5234 * library Help topic in the Help file.
5237 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5241 BSTR
*pbstrHelpString
,
5242 DWORD
*pdwHelpStringContext
,
5243 BSTR
*pbstrHelpStringDll
)
5245 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5249 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5251 /* the help string should be obtained from the helpstringdll,
5252 * using the _DLLGetDocumentation function, based on the supplied
5253 * lcid. Nice to do sometime...
5257 /* documentation for the typelib */
5259 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5260 if(pdwHelpStringContext
)
5261 *pdwHelpStringContext
=This
->dwHelpContext
;
5262 if(pbstrHelpStringDll
)
5263 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5269 /* for a typeinfo */
5270 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5272 if(SUCCEEDED(result
))
5274 ITypeInfo2
* pTInfo2
;
5275 result
= ITypeInfo_QueryInterface(pTInfo
,
5277 (LPVOID
*) &pTInfo2
);
5279 if(SUCCEEDED(result
))
5281 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5285 pdwHelpStringContext
,
5286 pbstrHelpStringDll
);
5288 ITypeInfo2_Release(pTInfo2
);
5291 ITypeInfo_Release(pTInfo
);
5297 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5299 TLBCustData
*pCData
;
5303 ct
= list_count(custdata_list
);
5305 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5306 if(!pCustData
->prgCustData
)
5307 return E_OUTOFMEMORY
;
5309 pCustData
->cCustData
= ct
;
5311 cdi
= pCustData
->prgCustData
;
5312 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5313 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5314 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5322 /* ITypeLib2::GetAllCustData
5324 * Gets all custom data items for the library.
5327 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5329 CUSTDATA
*pCustData
)
5331 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5332 TRACE("(%p)->(%p)\n", This
, pCustData
);
5333 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5336 static const ITypeLib2Vtbl tlbvt
= {
5337 ITypeLib2_fnQueryInterface
,
5339 ITypeLib2_fnRelease
,
5340 ITypeLib2_fnGetTypeInfoCount
,
5341 ITypeLib2_fnGetTypeInfo
,
5342 ITypeLib2_fnGetTypeInfoType
,
5343 ITypeLib2_fnGetTypeInfoOfGuid
,
5344 ITypeLib2_fnGetLibAttr
,
5345 ITypeLib2_fnGetTypeComp
,
5346 ITypeLib2_fnGetDocumentation
,
5348 ITypeLib2_fnFindName
,
5349 ITypeLib2_fnReleaseTLibAttr
,
5351 ITypeLib2_fnGetCustData
,
5352 ITypeLib2_fnGetLibStatistics
,
5353 ITypeLib2_fnGetDocumentation2
,
5354 ITypeLib2_fnGetAllCustData
5358 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5360 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5362 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5365 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5367 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5369 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5372 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5374 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5376 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5379 static HRESULT WINAPI
ITypeLibComp_fnBind(
5384 ITypeInfo
** ppTInfo
,
5385 DESCKIND
* pDescKind
,
5388 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5389 BOOL typemismatch
= FALSE
;
5392 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5394 *pDescKind
= DESCKIND_NONE
;
5395 pBindPtr
->lptcomp
= NULL
;
5398 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5399 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5400 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5402 /* FIXME: check wFlags here? */
5403 /* FIXME: we should use a hash table to look this info up using lHash
5404 * instead of an O(n) search */
5405 if ((pTypeInfo
->typekind
== TKIND_ENUM
) ||
5406 (pTypeInfo
->typekind
== TKIND_MODULE
))
5408 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5410 *pDescKind
= DESCKIND_TYPECOMP
;
5411 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5412 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5413 TRACE("module or enum: %s\n", debugstr_w(szName
));
5418 if ((pTypeInfo
->typekind
== TKIND_MODULE
) ||
5419 (pTypeInfo
->typekind
== TKIND_ENUM
))
5421 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5424 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5425 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5427 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5430 else if (hr
== TYPE_E_TYPEMISMATCH
)
5431 typemismatch
= TRUE
;
5434 if ((pTypeInfo
->typekind
== TKIND_COCLASS
) &&
5435 (pTypeInfo
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5437 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5439 ITypeInfo
*subtypeinfo
;
5441 DESCKIND subdesckind
;
5443 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5444 &subtypeinfo
, &subdesckind
, &subbindptr
);
5445 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5447 TYPEDESC tdesc_appobject
;
5448 const VARDESC vardesc_appobject
=
5451 NULL
, /* lpstrSchema */
5466 VAR_STATIC
/* varkind */
5469 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5470 tdesc_appobject
.vt
= VT_USERDEFINED
;
5472 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5474 /* cleanup things filled in by Bind call so we can put our
5475 * application object data in there instead */
5476 switch (subdesckind
)
5478 case DESCKIND_FUNCDESC
:
5479 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5481 case DESCKIND_VARDESC
:
5482 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5487 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5489 if (pTypeInfo
->hreftype
== -1)
5490 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5492 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5496 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5497 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5498 ITypeInfo_AddRef(*ppTInfo
);
5501 else if (hr
== TYPE_E_TYPEMISMATCH
)
5502 typemismatch
= TRUE
;
5508 TRACE("type mismatch %s\n", debugstr_w(szName
));
5509 return TYPE_E_TYPEMISMATCH
;
5513 TRACE("name not found %s\n", debugstr_w(szName
));
5518 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5522 ITypeInfo
** ppTInfo
,
5523 ITypeComp
** ppTComp
)
5525 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5526 ITypeInfoImpl
*info
;
5528 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5530 if(!szName
|| !ppTInfo
|| !ppTComp
)
5531 return E_INVALIDARG
;
5533 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5540 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5541 ITypeInfo_AddRef(*ppTInfo
);
5542 *ppTComp
= &info
->ITypeComp_iface
;
5543 ITypeComp_AddRef(*ppTComp
);
5548 static const ITypeCompVtbl tlbtcvt
=
5551 ITypeLibComp_fnQueryInterface
,
5552 ITypeLibComp_fnAddRef
,
5553 ITypeLibComp_fnRelease
,
5555 ITypeLibComp_fnBind
,
5556 ITypeLibComp_fnBindType
5559 /*================== ITypeInfo(2) Methods ===================================*/
5560 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5562 ITypeInfoImpl
*pTypeInfoImpl
;
5564 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5567 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5568 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5569 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5570 pTypeInfoImpl
->ref
= 0;
5571 pTypeInfoImpl
->hreftype
= -1;
5572 pTypeInfoImpl
->memidConstructor
= MEMBERID_NIL
;
5573 pTypeInfoImpl
->memidDestructor
= MEMBERID_NIL
;
5574 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5575 list_init(pTypeInfoImpl
->pcustdata_list
);
5577 TRACE("(%p)\n", pTypeInfoImpl
);
5578 return pTypeInfoImpl
;
5581 /* ITypeInfo::QueryInterface
5583 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5588 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5590 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5593 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5594 IsEqualIID(riid
,&IID_ITypeInfo
)||
5595 IsEqualIID(riid
,&IID_ITypeInfo2
))
5597 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5598 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5599 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5602 ITypeInfo2_AddRef(iface
);
5603 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5606 TRACE("-- Interface: E_NOINTERFACE\n");
5607 return E_NOINTERFACE
;
5610 /* ITypeInfo::AddRef
5612 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5614 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5615 ULONG ref
= InterlockedIncrement(&This
->ref
);
5617 TRACE("(%p)->ref is %u\n",This
, ref
);
5619 if (ref
== 1 /* incremented from 0 */)
5620 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5625 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5629 TRACE("destroying ITypeInfo(%p)\n",This
);
5631 for (i
= 0; i
< This
->cFuncs
; ++i
)
5634 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5635 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5637 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5638 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5639 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5640 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5642 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5643 heap_free(pFInfo
->pParamDesc
);
5644 TLB_FreeCustData(&pFInfo
->custdata_list
);
5646 heap_free(This
->funcdescs
);
5648 for(i
= 0; i
< This
->cVars
; ++i
)
5650 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5651 if (pVInfo
->vardesc_create
) {
5652 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5653 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5654 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5655 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5657 TLB_FreeCustData(&pVInfo
->custdata_list
);
5659 heap_free(This
->vardescs
);
5661 if(This
->impltypes
){
5662 for (i
= 0; i
< This
->cImplTypes
; ++i
){
5663 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5664 TLB_FreeCustData(&pImpl
->custdata_list
);
5666 heap_free(This
->impltypes
);
5669 TLB_FreeCustData(&This
->custdata_list
);
5674 /* ITypeInfo::Release
5676 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5678 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5679 ULONG ref
= InterlockedDecrement(&This
->ref
);
5681 TRACE("(%p)->(%u)\n",This
, ref
);
5685 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5686 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5687 if (not_attached_to_typelib
)
5689 /* otherwise This will be freed when typelib is freed */
5695 /* ITypeInfo::GetTypeAttr
5697 * Retrieves a TYPEATTR structure that contains the attributes of the type
5701 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5702 LPTYPEATTR
*ppTypeAttr
)
5704 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5707 TRACE("(%p)\n",This
);
5709 size
= sizeof(**ppTypeAttr
);
5710 if (This
->typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5711 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5713 *ppTypeAttr
= heap_alloc(size
);
5715 return E_OUTOFMEMORY
;
5717 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5718 (*ppTypeAttr
)->lcid
= This
->lcid
;
5719 (*ppTypeAttr
)->memidConstructor
= This
->memidConstructor
;
5720 (*ppTypeAttr
)->memidDestructor
= This
->memidDestructor
;
5721 (*ppTypeAttr
)->lpstrSchema
= This
->lpstrSchema
;
5722 (*ppTypeAttr
)->cbSizeInstance
= This
->cbSizeInstance
;
5723 (*ppTypeAttr
)->typekind
= This
->typekind
;
5724 (*ppTypeAttr
)->cFuncs
= This
->cFuncs
;
5725 (*ppTypeAttr
)->cVars
= This
->cVars
;
5726 (*ppTypeAttr
)->cImplTypes
= This
->cImplTypes
;
5727 (*ppTypeAttr
)->cbSizeVft
= This
->cbSizeVft
;
5728 (*ppTypeAttr
)->cbAlignment
= This
->cbAlignment
;
5729 (*ppTypeAttr
)->wTypeFlags
= This
->wTypeFlags
;
5730 (*ppTypeAttr
)->wMajorVerNum
= This
->wMajorVerNum
;
5731 (*ppTypeAttr
)->wMinorVerNum
= This
->wMinorVerNum
;
5732 (*ppTypeAttr
)->idldescType
= This
->idldescType
;
5734 if (This
->tdescAlias
)
5735 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5736 This
->tdescAlias
, *ppTypeAttr
+ 1);
5738 (*ppTypeAttr
)->tdescAlias
.vt
= VT_EMPTY
;
5739 (*ppTypeAttr
)->tdescAlias
.u
.lptdesc
= NULL
;
5742 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5743 /* This should include all the inherited funcs */
5744 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5745 /* This is always the size of IDispatch's vtbl */
5746 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5747 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5752 /* ITypeInfo::GetTypeComp
5754 * Retrieves the ITypeComp interface for the type description, which enables a
5755 * client compiler to bind to the type description's members.
5758 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5759 ITypeComp
* *ppTComp
)
5761 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5763 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5765 *ppTComp
= &This
->ITypeComp_iface
;
5766 ITypeComp_AddRef(*ppTComp
);
5770 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5772 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5773 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5774 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5778 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5781 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5782 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5784 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5785 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5786 *buffer
+= sizeof(PARAMDESCEX
);
5787 *pparamdescex_dest
= *pparamdescex_src
;
5788 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5789 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5790 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5791 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5794 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5798 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5800 UINT len
= SysStringLen(str
), i
;
5801 for (i
= 0; i
< len
; ++i
)
5807 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5809 if (V_VT(var
) == VT_INT
)
5810 return VariantChangeType(var
, var
, 0, VT_I4
);
5811 else if (V_VT(var
) == VT_UINT
)
5812 return VariantChangeType(var
, var
, 0, VT_UI4
);
5813 else if (V_VT(var
) == VT_BSTR
)
5814 return TLB_SanitizeBSTR(V_BSTR(var
));
5819 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5821 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5822 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5825 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5829 SIZE_T size
= sizeof(*src
);
5833 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5834 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5835 for (i
= 0; i
< src
->cParams
; i
++)
5837 size
+= sizeof(ELEMDESC
);
5838 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5841 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5842 if (!dest
) return E_OUTOFMEMORY
;
5845 if (dispinterface
) /* overwrite funckind */
5846 dest
->funckind
= FUNC_DISPATCH
;
5847 buffer
= (char *)(dest
+ 1);
5849 dest
->oVft
= dest
->oVft
& 0xFFFC;
5851 if (dest
->cScodes
) {
5852 dest
->lprgscode
= (SCODE
*)buffer
;
5853 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5854 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5856 dest
->lprgscode
= NULL
;
5858 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5861 SysFreeString((BSTR
)dest
);
5865 if (dest
->cParams
) {
5866 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5867 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5868 for (i
= 0; i
< src
->cParams
; i
++)
5870 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5876 /* undo the above actions */
5877 for (i
= i
- 1; i
>= 0; i
--)
5878 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5879 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5880 SysFreeString((BSTR
)dest
);
5884 dest
->lprgelemdescParam
= NULL
;
5886 /* special treatment for dispinterfaces: this makes functions appear
5887 * to return their [retval] value when it is really returning an
5889 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5891 if (dest
->cParams
&&
5892 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5894 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5895 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5897 ERR("elemdesc should have started with VT_PTR instead of:\n");
5899 dump_ELEMDESC(elemdesc
);
5900 return E_UNEXPECTED
;
5903 /* copy last parameter to the return value. we are using a flat
5904 * buffer so there is no danger of leaking memory in
5906 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5908 /* remove the last parameter */
5912 /* otherwise this function is made to appear to have no return
5914 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5922 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5924 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5925 if (var_desc
->varkind
== VAR_CONST
)
5926 VariantClear(var_desc
->u
.lpvarValue
);
5927 SysFreeString((BSTR
)var_desc
);
5930 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5932 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5934 if (index
>= This
->cFuncs
)
5935 return TYPE_E_ELEMENTNOTFOUND
;
5937 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5941 /* internal function to make the inherited interfaces' methods appear
5942 * part of the interface */
5943 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5944 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5946 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5948 UINT implemented_funcs
= 0;
5953 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5957 ITypeInfo
*pSubTypeInfo
;
5960 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5964 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5967 &sub_funcs
, hrefoffset
);
5968 implemented_funcs
+= sub_funcs
;
5969 ITypeInfo_Release(pSubTypeInfo
);
5972 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5976 *funcs
= implemented_funcs
+ This
->cFuncs
;
5980 if (index
< implemented_funcs
)
5981 return E_INVALIDARG
;
5982 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5986 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5988 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5991 switch (pTypeDesc
->vt
)
5993 case VT_USERDEFINED
:
5994 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5998 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
6001 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
6009 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
6012 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6013 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
6014 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
6017 /* ITypeInfo::GetFuncDesc
6019 * Retrieves the FUNCDESC structure that contains information about a
6020 * specified function.
6023 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
6024 LPFUNCDESC
*ppFuncDesc
)
6026 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6027 const FUNCDESC
*internal_funcdesc
;
6029 UINT hrefoffset
= 0;
6031 TRACE("(%p) index %d\n", This
, index
);
6034 return E_INVALIDARG
;
6036 if (This
->needs_layout
)
6037 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6039 if (This
->typekind
== TKIND_DISPATCH
)
6040 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
6041 &internal_funcdesc
, NULL
,
6044 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6045 &internal_funcdesc
);
6048 WARN("description for function %d not found\n", index
);
6052 hr
= TLB_AllocAndInitFuncDesc(
6055 This
->typekind
== TKIND_DISPATCH
);
6057 if ((This
->typekind
== TKIND_DISPATCH
) && hrefoffset
)
6058 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6060 TRACE("-- 0x%08x\n", hr
);
6064 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6068 SIZE_T size
= sizeof(*src
);
6071 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6072 if (src
->varkind
== VAR_CONST
)
6073 size
+= sizeof(VARIANT
);
6074 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6076 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6077 if (!dest
) return E_OUTOFMEMORY
;
6080 buffer
= (char *)(dest
+ 1);
6081 if (src
->lpstrSchema
)
6084 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6085 len
= strlenW(src
->lpstrSchema
);
6086 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6087 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6090 if (src
->varkind
== VAR_CONST
)
6094 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6095 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6096 buffer
+= sizeof(VARIANT
);
6097 VariantInit(dest
->u
.lpvarValue
);
6098 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6101 SysFreeString((BSTR
)dest
);
6105 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6108 if (src
->varkind
== VAR_CONST
)
6109 VariantClear(dest
->u
.lpvarValue
);
6110 SysFreeString((BSTR
)dest
);
6117 /* ITypeInfo::GetVarDesc
6119 * Retrieves a VARDESC structure that describes the specified variable.
6122 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6123 LPVARDESC
*ppVarDesc
)
6125 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6126 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6128 TRACE("(%p) index %d\n", This
, index
);
6130 if(index
>= This
->cVars
)
6131 return TYPE_E_ELEMENTNOTFOUND
;
6133 if (This
->needs_layout
)
6134 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6136 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6139 /* ITypeInfo_GetNames
6141 * Retrieves the variable with the specified member ID (or the name of the
6142 * property or method and its parameters) that correspond to the specified
6145 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6146 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6148 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6149 const TLBFuncDesc
*pFDesc
;
6150 const TLBVarDesc
*pVDesc
;
6152 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6155 return E_INVALIDARG
;
6159 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
6162 if(!cMaxNames
|| !pFDesc
->Name
)
6165 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6168 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6169 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6171 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6177 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
6180 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6185 if(This
->impltypes
&&
6186 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
6187 /* recursive search */
6190 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6191 if(SUCCEEDED(result
))
6193 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6194 ITypeInfo_Release(pTInfo
);
6197 WARN("Could not search inherited interface!\n");
6201 WARN("no names found\n");
6204 return TYPE_E_ELEMENTNOTFOUND
;
6210 /* ITypeInfo::GetRefTypeOfImplType
6212 * If a type description describes a COM class, it retrieves the type
6213 * description of the implemented interface types. For an interface,
6214 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6218 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6223 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6226 TRACE("(%p) index %d\n", This
, index
);
6227 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6231 /* only valid on dual interfaces;
6232 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6235 if (This
->wTypeFlags
& TYPEFLAG_FDUAL
)
6241 hr
= TYPE_E_ELEMENTNOTFOUND
;
6244 else if(index
== 0 && This
->typekind
== TKIND_DISPATCH
)
6246 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6247 *pRefType
= This
->pTypeLib
->dispatch_href
;
6251 if(index
>= This
->cImplTypes
)
6252 hr
= TYPE_E_ELEMENTNOTFOUND
;
6254 *pRefType
= This
->impltypes
[index
].hRef
;
6255 if(This
->typekind
== TKIND_INTERFACE
)
6263 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6265 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6271 /* ITypeInfo::GetImplTypeFlags
6273 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6274 * or base interface in a type description.
6276 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6277 UINT index
, INT
*pImplTypeFlags
)
6279 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6281 TRACE("(%p) index %d\n", This
, index
);
6284 return E_INVALIDARG
;
6286 if(This
->typekind
== TKIND_DISPATCH
&& index
== 0){
6287 *pImplTypeFlags
= 0;
6291 if(index
>= This
->cImplTypes
)
6292 return TYPE_E_ELEMENTNOTFOUND
;
6294 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6300 * Maps between member names and member IDs, and parameter names and
6303 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6304 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6306 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6307 const TLBVarDesc
*pVDesc
;
6311 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6314 /* init out parameters in case of failure */
6315 for (i
= 0; i
< cNames
; i
++)
6316 pMemId
[i
] = MEMBERID_NIL
;
6318 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
) {
6320 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6321 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6322 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6323 for(i
=1; i
< cNames
; i
++){
6324 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6325 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6327 if( j
<pFDesc
->funcdesc
.cParams
)
6330 ret
=DISP_E_UNKNOWNNAME
;
6332 TRACE("-- 0x%08x\n", ret
);
6336 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, *rgszNames
);
6339 *pMemId
= pVDesc
->vardesc
.memid
;
6342 /* not found, see if it can be found in an inherited interface */
6343 if(This
->impltypes
) {
6344 /* recursive search */
6346 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6348 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6349 ITypeInfo_Release(pTInfo
);
6352 WARN("Could not search inherited interface!\n");
6354 WARN("no names found\n");
6355 return DISP_E_UNKNOWNNAME
;
6361 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6362 __ASM_GLOBAL_FUNC( call_method
,
6364 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6365 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6366 "movl %esp,%ebp\n\t"
6367 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6369 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6371 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6372 "movl 12(%ebp),%edx\n\t"
6373 "movl %esp,%edi\n\t"
6376 "subl %edx,%edi\n\t"
6377 "andl $~15,%edi\n\t"
6378 "movl %edi,%esp\n\t"
6379 "movl 12(%ebp),%ecx\n\t"
6380 "movl 16(%ebp),%esi\n\t"
6383 "1:\tcall *8(%ebp)\n\t"
6384 "subl %esp,%edi\n\t"
6385 "movl 20(%ebp),%ecx\n\t"
6386 "movl %edi,(%ecx)\n\t"
6387 "leal -8(%ebp),%esp\n\t"
6389 __ASM_CFI(".cfi_same_value %edi\n\t")
6391 __ASM_CFI(".cfi_same_value %esi\n\t")
6393 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6394 __ASM_CFI(".cfi_same_value %ebp\n\t")
6397 /* same function but returning floating point */
6398 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6400 /* ITypeInfo::Invoke
6402 * Invokes a method, or accesses a property of an object, that implements the
6403 * interface described by the type description.
6406 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6410 if (TRACE_ON(ole
)) {
6412 TRACE("Calling %p(",func
);
6413 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6414 if (nrargs
> 30) TRACE("...");
6421 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6424 FIXME("unsupported calling convention %d\n",callconv
);
6428 TRACE("returns %08x\n",res
);
6432 #elif defined(__x86_64__)
6434 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6435 __ASM_GLOBAL_FUNC( call_method
,
6437 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6438 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6439 "movq %rsp,%rbp\n\t"
6440 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6442 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6444 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6445 "movq %rcx,%rax\n\t"
6448 "cmovgq %rdx,%rcx\n\t"
6449 "leaq 0(,%rcx,8),%rdx\n\t"
6450 "subq %rdx,%rsp\n\t"
6451 "andq $~15,%rsp\n\t"
6452 "movq %rsp,%rdi\n\t"
6455 "movq 0(%rsp),%rcx\n\t"
6456 "movq 8(%rsp),%rdx\n\t"
6457 "movq 16(%rsp),%r8\n\t"
6458 "movq 24(%rsp),%r9\n\t"
6459 "movq %rcx,%xmm0\n\t"
6460 "movq %rdx,%xmm1\n\t"
6461 "movq %r8,%xmm2\n\t"
6462 "movq %r9,%xmm3\n\t"
6464 "leaq -16(%rbp),%rsp\n\t"
6466 __ASM_CFI(".cfi_same_value %rdi\n\t")
6468 __ASM_CFI(".cfi_same_value %rsi\n\t")
6469 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6471 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6472 __ASM_CFI(".cfi_same_value %rbp\n\t")
6475 /* same function but returning floating point */
6476 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6478 #endif /* __x86_64__ */
6480 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6483 ITypeInfo
*tinfo2
= NULL
;
6484 TYPEATTR
*tattr
= NULL
;
6486 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6489 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6491 tdesc
->u
.hreftype
, hr
);
6494 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6497 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6498 ITypeInfo_Release(tinfo2
);
6502 switch (tattr
->typekind
)
6509 tdesc
= &tattr
->tdescAlias
;
6510 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6513 case TKIND_INTERFACE
:
6514 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6520 case TKIND_DISPATCH
:
6529 FIXME("TKIND_RECORD unhandled.\n");
6534 FIXME("TKIND_UNION unhandled.\n");
6539 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6543 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6544 ITypeInfo_Release(tinfo2
);
6548 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6552 /* enforce only one level of pointer indirection */
6553 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6555 tdesc
= tdesc
->u
.lptdesc
;
6557 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6558 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6559 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6560 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6561 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6563 VARTYPE vt_userdefined
= 0;
6564 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6565 if (tdesc
->vt
== VT_PTR
)
6567 vt_userdefined
= VT_BYREF
;
6568 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6570 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6572 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6573 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6575 *vt
|= vt_userdefined
;
6587 case VT_USERDEFINED
:
6588 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6595 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6596 hr
= DISP_E_BADVARTYPE
;
6600 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6615 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6621 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6625 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6627 ITypeInfo_Release(tinfo2
);
6631 switch(tattr
->typekind
) {
6633 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6636 case TKIND_INTERFACE
:
6637 case TKIND_DISPATCH
:
6638 *guid
= tattr
->guid
;
6642 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6643 hres
= E_UNEXPECTED
;
6646 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6647 ITypeInfo_Release(tinfo2
);
6651 /***********************************************************************
6652 * DispCallFunc (OLEAUT32.@)
6654 * Invokes a function of the specified calling convention, passing the
6655 * specified arguments and returns the result.
6658 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6659 * oVft [I] The offset in the vtable. See notes.
6660 * cc [I] Calling convention of the function to call.
6661 * vtReturn [I] The return type of the function.
6662 * cActuals [I] Number of parameters.
6663 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6664 * prgpvarg [I] The arguments to pass.
6665 * pvargResult [O] The return value of the function. Can be NULL.
6669 * Failure: HRESULT code.
6672 * The HRESULT return value of this function is not affected by the return
6673 * value of the user supplied function, which is returned in pvargResult.
6675 * If pvInstance is NULL then a non-object function is to be called and oVft
6676 * is the address of the function to call.
6678 * The cc parameter can be one of the following values:
6691 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6692 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6695 int argspos
, stack_offset
;
6700 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6701 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6702 pvargResult
, V_VT(pvargResult
));
6704 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6706 FIXME("unsupported calling convention %d\n",cc
);
6707 return E_INVALIDARG
;
6710 /* maximum size for an argument is sizeof(VARIANT) */
6711 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6713 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6717 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6718 func
= vtable
[oVft
/sizeof(void *)];
6719 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6721 else func
= (void *)oVft
;
6723 for (i
= 0; i
< cActuals
; i
++)
6725 VARIANT
*arg
= prgpvarg
[i
];
6736 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6737 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6741 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6742 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6744 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6745 args
[argspos
++] = V_BOOL(arg
);
6748 args
[argspos
++] = V_UI4(arg
);
6751 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6757 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6760 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6764 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6768 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6769 call_method( func
, argspos
, args
, &stack_offset
);
6774 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6777 WARN("invalid return type %u\n", vtReturn
);
6779 return E_INVALIDARG
;
6781 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6785 if (stack_offset
&& cc
== CC_STDCALL
)
6787 WARN( "stack pointer off by %d\n", stack_offset
);
6788 return DISP_E_BADCALLEE
;
6790 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6791 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6794 #elif defined(__x86_64__)
6800 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6801 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6802 pvargResult
, V_VT(pvargResult
));
6804 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6806 FIXME("unsupported calling convention %d\n",cc
);
6807 return E_INVALIDARG
;
6810 /* maximum size for an argument is sizeof(DWORD_PTR) */
6811 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6813 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6817 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6818 func
= vtable
[oVft
/sizeof(void *)];
6819 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6821 else func
= (void *)oVft
;
6823 for (i
= 0; i
< cActuals
; i
++)
6825 VARIANT
*arg
= prgpvarg
[i
];
6831 args
[argspos
++] = (ULONG_PTR
)arg
;
6833 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6834 args
[argspos
++] = V_BOOL(arg
);
6837 args
[argspos
++] = V_UI8(arg
);
6840 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6846 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6850 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6854 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6855 call_method( func
, argspos
, args
);
6858 WARN("invalid return type %u\n", vtReturn
);
6860 return E_INVALIDARG
;
6862 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6866 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6867 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6871 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6872 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6877 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6879 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6882 #define INVBUF_ELEMENT_SIZE \
6883 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6884 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6885 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6886 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6887 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6888 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6889 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6890 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6892 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6897 DISPPARAMS
*pDispParams
,
6898 VARIANT
*pVarResult
,
6899 EXCEPINFO
*pExcepInfo
,
6902 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6904 unsigned int var_index
;
6907 const TLBFuncDesc
*pFuncInfo
;
6910 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6911 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6914 if( This
->wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6915 return DISP_E_MEMBERNOTFOUND
;
6919 ERR("NULL pDispParams not allowed\n");
6920 return E_INVALIDARG
;
6923 dump_DispParms(pDispParams
);
6925 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6927 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6928 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6929 return E_INVALIDARG
;
6932 /* we do this instead of using GetFuncDesc since it will return a fake
6933 * FUNCDESC for dispinterfaces and we want the real function description */
6934 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
6935 pFuncInfo
= &This
->funcdescs
[fdc
];
6936 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6937 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6938 !func_restricted( &pFuncInfo
->funcdesc
))
6942 if (fdc
< This
->cFuncs
) {
6943 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6947 TRACE("invoking:\n");
6948 dump_TLBFuncDescOne(pFuncInfo
);
6951 switch (func_desc
->funckind
) {
6952 case FUNC_PUREVIRTUAL
:
6953 case FUNC_VIRTUAL
: {
6954 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6956 VARIANT retval
; /* pointer for storing byref retvals in */
6957 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6958 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6959 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6960 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6961 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6962 UINT vargs_converted
=0;
6966 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6968 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6970 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6971 hres
= DISP_E_PARAMNOTFOUND
;
6976 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6978 ERR("functions with the vararg attribute do not support named arguments\n");
6979 hres
= DISP_E_NONAMEDARGS
;
6983 for (i
= 0; i
< func_desc
->cParams
; i
++)
6985 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6986 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6991 TRACE("changing args\n");
6992 for (i
= 0; i
< func_desc
->cParams
; i
++)
6994 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6995 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6996 VARIANTARG
*src_arg
;
6998 if (wParamFlags
& PARAMFLAG_FLCID
)
7001 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7003 V_I4(arg
) = This
->pTypeLib
->lcid
;
7012 for (j
= 0; j
< cNamedArgs
; j
++)
7013 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7015 src_arg
= &pDispParams
->rgvarg
[j
];
7020 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7022 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7026 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7028 /* under most conditions the caller is not allowed to
7029 * pass in a dispparam arg in the index of what would be
7030 * the retval parameter. however, there is an exception
7031 * where the extra parameter is used in an extra
7032 * IDispatch::Invoke below */
7033 if ((i
< pDispParams
->cArgs
) &&
7034 ((func_desc
->cParams
!= 1) || !pVarResult
||
7035 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7037 hres
= DISP_E_BADPARAMCOUNT
;
7041 /* note: this check is placed so that if the caller passes
7042 * in a VARIANTARG for the retval we just ignore it, like
7044 if (i
== func_desc
->cParams
- 1)
7047 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7048 memset(arg
, 0, sizeof(*arg
));
7049 V_VT(arg
) = rgvt
[i
];
7050 memset(&retval
, 0, sizeof(retval
));
7051 V_BYREF(arg
) = &retval
;
7055 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7056 hres
= E_UNEXPECTED
;
7062 TRACE("%s\n", debugstr_variant(src_arg
));
7064 if(rgvt
[i
]!=V_VT(src_arg
))
7066 if (rgvt
[i
] == VT_VARIANT
)
7067 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7068 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7070 if (rgvt
[i
] == V_VT(src_arg
))
7071 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7074 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7075 if (wParamFlags
& PARAMFLAG_FIN
)
7076 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7077 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7079 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7081 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
7084 SAFEARRAYBOUND bound
;
7088 bound
.cElements
= pDispParams
->cArgs
-i
;
7089 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7091 ERR("SafeArrayCreate failed\n");
7094 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7097 ERR("SafeArrayAccessData failed with %x\n", hres
);
7098 SafeArrayDestroy(a
);
7101 for (j
= 0; j
< bound
.cElements
; j
++)
7102 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7103 hres
= SafeArrayUnaccessData(a
);
7106 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7107 SafeArrayDestroy(a
);
7110 V_ARRAY(&rgvarg
[i
]) = a
;
7111 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7113 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7115 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7116 if (wParamFlags
& PARAMFLAG_FIN
)
7117 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7119 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7120 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7121 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7123 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7125 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7126 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7130 /* FIXME: this doesn't work for VT_BYREF arguments if
7131 * they are not the same type as in the paramdesc */
7132 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7133 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7134 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7139 ERR("failed to convert param %d to %s from %s\n", i
,
7140 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7143 prgpvarg
[i
] = &rgvarg
[i
];
7147 prgpvarg
[i
] = src_arg
;
7150 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7151 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7152 && V_UNKNOWN(prgpvarg
[i
])) {
7153 IUnknown
*userdefined_iface
;
7156 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7160 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7162 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7166 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7167 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7170 else if (wParamFlags
& PARAMFLAG_FOPT
)
7173 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7174 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7176 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7182 VARIANTARG
*missing_arg
;
7183 /* if the function wants a pointer to a variant then
7184 * set that up, otherwise just pass the VT_ERROR in
7185 * the argument by value */
7186 if (rgvt
[i
] & VT_BYREF
)
7188 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7189 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7190 V_VARIANTREF(arg
) = missing_arg
;
7194 V_VT(missing_arg
) = VT_ERROR
;
7195 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7200 hres
= DISP_E_BADPARAMCOUNT
;
7204 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7206 /* VT_VOID is a special case for return types, so it is not
7207 * handled in the general function */
7208 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7209 V_VT(&varresult
) = VT_EMPTY
;
7212 V_VT(&varresult
) = 0;
7213 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7214 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7217 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7218 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7219 prgpvarg
, &varresult
);
7221 vargs_converted
= 0;
7223 for (i
= 0; i
< func_desc
->cParams
; i
++)
7225 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7226 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7228 if (wParamFlags
& PARAMFLAG_FLCID
)
7230 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7232 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7236 VariantInit(pVarResult
);
7237 /* deref return value */
7238 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7241 VARIANT_ClearInd(prgpvarg
[i
]);
7243 else if (vargs_converted
< pDispParams
->cArgs
)
7245 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7246 if (wParamFlags
& PARAMFLAG_FOUT
)
7248 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7250 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7254 ERR("failed to convert param %d to vt %d\n", i
,
7255 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7260 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7261 func_desc
->cParamsOpt
< 0 &&
7262 i
== func_desc
->cParams
-1)
7264 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7267 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7270 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7273 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7276 ERR("SafeArrayAccessData failed with %x\n", hres
);
7279 for (j
= 0; j
<= ubound
; j
++)
7280 VariantClear(&v
[j
]);
7281 hres
= SafeArrayUnaccessData(a
);
7284 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7288 VariantClear(&rgvarg
[i
]);
7291 else if (wParamFlags
& PARAMFLAG_FOPT
)
7293 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7294 VariantClear(&rgvarg
[i
]);
7297 VariantClear(&missing_arg
[i
]);
7300 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7302 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7303 hres
= DISP_E_EXCEPTION
;
7306 IErrorInfo
*pErrorInfo
;
7307 pExcepInfo
->scode
= V_ERROR(&varresult
);
7308 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7310 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7311 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7312 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7313 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7315 IErrorInfo_Release(pErrorInfo
);
7319 if (V_VT(&varresult
) != VT_ERROR
)
7321 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7325 VariantClear(pVarResult
);
7326 *pVarResult
= varresult
;
7329 VariantClear(&varresult
);
7332 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7333 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7334 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7335 (pDispParams
->cArgs
!= 0))
7337 if (V_VT(pVarResult
) == VT_DISPATCH
)
7339 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7340 /* Note: not VariantClear; we still need the dispatch
7341 * pointer to be valid */
7342 VariantInit(pVarResult
);
7343 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7344 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7345 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7346 IDispatch_Release(pDispatch
);
7350 VariantClear(pVarResult
);
7351 hres
= DISP_E_NOTACOLLECTION
;
7359 case FUNC_DISPATCH
: {
7362 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7363 if (SUCCEEDED(hres
)) {
7364 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7365 hres
= IDispatch_Invoke(
7366 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7367 pVarResult
,pExcepInfo
,pArgErr
7370 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7371 IDispatch_Release(disp
);
7373 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7377 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7382 TRACE("-- 0x%08x\n", hres
);
7385 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7388 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7389 if(FAILED(hres
)) return hres
;
7391 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7392 dump_VARDESC(var_desc
);
7393 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7397 /* not found, look for it in inherited interfaces */
7398 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7399 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7400 if(This
->impltypes
) {
7401 /* recursive search */
7403 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7404 if(SUCCEEDED(hres
)){
7405 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7406 ITypeInfo_Release(pTInfo
);
7409 WARN("Could not search inherited interface!\n");
7412 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7413 return DISP_E_MEMBERNOTFOUND
;
7416 /* ITypeInfo::GetDocumentation
7418 * Retrieves the documentation string, the complete Help file name and path,
7419 * and the context ID for the Help topic for a specified type description.
7421 * (Can be tested by the Visual Basic Editor in Word for instance.)
7423 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7424 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7425 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7427 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7428 const TLBFuncDesc
*pFDesc
;
7429 const TLBVarDesc
*pVDesc
;
7430 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7431 " HelpContext(%p) HelpFile(%p)\n",
7432 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7433 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7435 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7437 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7439 *pdwHelpContext
=This
->dwHelpContext
;
7441 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7443 }else {/* for a member */
7444 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7447 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7449 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7451 *pdwHelpContext
=pFDesc
->helpcontext
;
7453 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7456 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7459 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7461 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7463 *pdwHelpContext
=pVDesc
->HelpContext
;
7465 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7470 if(This
->impltypes
&&
7471 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
7472 /* recursive search */
7475 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7476 if(SUCCEEDED(result
)) {
7477 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7478 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7479 ITypeInfo_Release(pTInfo
);
7482 WARN("Could not search inherited interface!\n");
7485 WARN("member %d not found\n", memid
);
7486 return TYPE_E_ELEMENTNOTFOUND
;
7489 /* ITypeInfo::GetDllEntry
7491 * Retrieves a description or specification of an entry point for a function
7494 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7495 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7498 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7499 const TLBFuncDesc
*pFDesc
;
7501 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7503 if (pBstrDllName
) *pBstrDllName
= NULL
;
7504 if (pBstrName
) *pBstrName
= NULL
;
7505 if (pwOrdinal
) *pwOrdinal
= 0;
7507 if (This
->typekind
!= TKIND_MODULE
)
7508 return TYPE_E_BADMODULEKIND
;
7510 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7512 dump_TypeInfo(This
);
7514 dump_TLBFuncDescOne(pFDesc
);
7517 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7519 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7521 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7529 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7532 return TYPE_E_ELEMENTNOTFOUND
;
7535 /* internal function to make the inherited interfaces' methods appear
7536 * part of the interface */
7537 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7538 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7540 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7543 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7545 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7547 ITypeInfo
*pSubTypeInfo
;
7549 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7553 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7555 ITypeInfo_Release(pSubTypeInfo
);
7559 *hRefType
-= DISPATCH_HREF_OFFSET
;
7561 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7562 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7567 struct search_res_tlb_params
7573 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7575 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7576 static const WCHAR formatW
[] = {'\\','%','d',0};
7577 WCHAR szPath
[MAX_PATH
+1];
7578 ITypeLib
*pTLib
= NULL
;
7582 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7585 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7588 if (snprintfW(szPath
+ len
, sizeof(szPath
)/sizeof(WCHAR
) - len
, formatW
, LOWORD(lpszName
)) < 0)
7591 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7594 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7595 if (IsEqualGUID(params
->guid
, impl
->guid
))
7597 params
->pTLib
= pTLib
;
7598 return FALSE
; /* stop enumeration */
7600 ITypeLib_Release(pTLib
);
7606 /* ITypeInfo::GetRefTypeInfo
7608 * If a type description references other type descriptions, it retrieves
7609 * the referenced type descriptions.
7611 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7614 ITypeInfo
**ppTInfo
)
7616 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7617 HRESULT result
= E_FAIL
;
7620 return E_INVALIDARG
;
7622 if ((INT
)hRefType
< 0) {
7623 ITypeInfoImpl
*pTypeInfoImpl
;
7625 if (!(This
->wTypeFlags
& TYPEFLAG_FDUAL
) ||
7626 !(This
->typekind
== TKIND_INTERFACE
||
7627 This
->typekind
== TKIND_DISPATCH
))
7628 return TYPE_E_ELEMENTNOTFOUND
;
7630 /* when we meet a DUAL typeinfo, we must create the alternate
7633 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7635 *pTypeInfoImpl
= *This
;
7636 pTypeInfoImpl
->ref
= 0;
7637 list_init(&pTypeInfoImpl
->custdata_list
);
7639 if (This
->typekind
== TKIND_INTERFACE
)
7640 pTypeInfoImpl
->typekind
= TKIND_DISPATCH
;
7642 pTypeInfoImpl
->typekind
= TKIND_INTERFACE
;
7644 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7645 /* the AddRef implicitly adds a reference to the parent typelib, which
7646 * stops the copied data from being destroyed until the new typeinfo's
7647 * refcount goes to zero, but we need to signal to the new instance to
7648 * not free its data structures when it is destroyed */
7649 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7651 ITypeInfo_AddRef(*ppTInfo
);
7654 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7655 (This
->typekind
== TKIND_DISPATCH
))
7657 HREFTYPE href_dispatch
= hRefType
;
7658 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7660 TLBRefType
*ref_type
;
7661 ITypeLib
*pTLib
= NULL
;
7664 if(!(hRefType
& 0x1)){
7665 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7667 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7670 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7671 ITypeInfo_AddRef(*ppTInfo
);
7677 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7679 if(ref_type
->reference
== (hRefType
& (~0x3)))
7682 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7684 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7688 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7690 TRACE("internal reference\n");
7691 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7693 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7694 TRACE("typeinfo in imported typelib that is already loaded\n");
7695 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7696 ITypeLib_AddRef(pTLib
);
7699 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
7700 struct search_res_tlb_params params
;
7703 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7705 /* Search in resource table */
7706 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
7707 params
.pTLib
= NULL
;
7708 EnumResourceNamesW(NULL
, TYPELIBW
, search_res_tlb
, (LONG_PTR
)¶ms
);
7709 pTLib
= params
.pTLib
;
7714 /* Search on disk */
7715 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7716 ref_type
->pImpTLInfo
->wVersionMajor
,
7717 ref_type
->pImpTLInfo
->wVersionMinor
,
7718 This
->pTypeLib
->syskind
,
7719 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7721 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7723 result
= LoadTypeLib(libnam
, &pTLib
);
7724 SysFreeString(libnam
);
7727 if(SUCCEEDED(result
)) {
7728 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7729 ITypeLib_AddRef(pTLib
);
7733 if(SUCCEEDED(result
)) {
7734 if(ref_type
->index
== TLB_REF_USE_GUID
)
7735 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7737 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7740 ITypeLib_Release(pTLib
);
7744 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7745 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7749 /* ITypeInfo::AddressOfMember
7751 * Retrieves the addresses of static functions or variables, such as those
7754 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7755 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7757 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7763 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7765 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7769 module
= LoadLibraryW(dll
);
7772 ERR("couldn't load %s\n", debugstr_w(dll
));
7774 SysFreeString(entry
);
7775 return STG_E_FILENOTFOUND
;
7777 /* FIXME: store library somewhere where we can free it */
7782 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7783 entryA
= heap_alloc(len
);
7784 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7786 *ppv
= GetProcAddress(module
, entryA
);
7788 ERR("function not found %s\n", debugstr_a(entryA
));
7794 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7796 ERR("function not found %d\n", ordinal
);
7800 SysFreeString(entry
);
7803 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7808 /* ITypeInfo::CreateInstance
7810 * Creates a new instance of a type that describes a component object class
7813 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7814 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7816 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7820 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7826 WARN("Not able to aggregate\n");
7827 return CLASS_E_NOAGGREGATION
;
7830 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7831 if(FAILED(hr
)) return hr
;
7833 if(pTA
->typekind
!= TKIND_COCLASS
)
7835 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7841 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7844 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7845 TRACE("GetActiveObject rets %08x\n", hr
);
7848 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7849 IUnknown_Release(pUnk
);
7854 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7855 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7859 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7863 /* ITypeInfo::GetMops
7865 * Retrieves marshalling information.
7867 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7870 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7871 FIXME("(%p %d) stub!\n", This
, memid
);
7876 /* ITypeInfo::GetContainingTypeLib
7878 * Retrieves the containing type library and the index of the type description
7879 * within that type library.
7881 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7882 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7884 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7886 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7888 *pIndex
=This
->index
;
7889 TRACE("returning pIndex=%d\n", *pIndex
);
7893 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7894 ITypeLib_AddRef(*ppTLib
);
7895 TRACE("returning ppTLib=%p\n", *ppTLib
);
7901 /* ITypeInfo::ReleaseTypeAttr
7903 * Releases a TYPEATTR previously returned by Get
7906 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7907 TYPEATTR
* pTypeAttr
)
7909 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7910 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7911 heap_free(pTypeAttr
);
7914 /* ITypeInfo::ReleaseFuncDesc
7916 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7918 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7920 FUNCDESC
*pFuncDesc
)
7922 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7925 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7927 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7928 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7929 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7931 SysFreeString((BSTR
)pFuncDesc
);
7934 /* ITypeInfo::ReleaseVarDesc
7936 * Releases a VARDESC previously returned by GetVarDesc.
7938 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7941 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7942 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7944 TLB_FreeVarDesc(pVarDesc
);
7947 /* ITypeInfo2::GetTypeKind
7949 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7952 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7953 TYPEKIND
*pTypeKind
)
7955 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7956 *pTypeKind
=This
->typekind
;
7957 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7961 /* ITypeInfo2::GetTypeFlags
7963 * Returns the type flags without any allocations. This returns a DWORD type
7964 * flag, which expands the type flags without growing the TYPEATTR (type
7968 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7970 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7971 *pTypeFlags
=This
->wTypeFlags
;
7972 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7976 /* ITypeInfo2::GetFuncIndexOfMemId
7977 * Binds to a specific member based on a known DISPID, where the member name
7978 * is not known (for example, when binding to a default member).
7981 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7982 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7984 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7988 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
7989 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7990 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7993 if(fdc
< This
->cFuncs
) {
7997 result
= TYPE_E_ELEMENTNOTFOUND
;
7999 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
8000 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8004 /* TypeInfo2::GetVarIndexOfMemId
8006 * Binds to a specific member based on a known DISPID, where the member name
8007 * is not known (for example, when binding to a default member).
8010 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8011 MEMBERID memid
, UINT
*pVarIndex
)
8013 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8014 TLBVarDesc
*pVarInfo
;
8016 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8018 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8020 return TYPE_E_ELEMENTNOTFOUND
;
8022 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8027 /* ITypeInfo2::GetCustData
8029 * Gets the custom data
8031 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8036 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8037 TLBCustData
*pCData
;
8039 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8041 if(!guid
|| !pVarVal
)
8042 return E_INVALIDARG
;
8044 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8046 VariantInit( pVarVal
);
8048 VariantCopy( pVarVal
, &pCData
->data
);
8050 VariantClear( pVarVal
);
8054 /* ITypeInfo2::GetFuncCustData
8056 * Gets the custom data
8058 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8064 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8065 TLBCustData
*pCData
;
8066 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8068 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8070 if(index
>= This
->cFuncs
)
8071 return TYPE_E_ELEMENTNOTFOUND
;
8073 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8075 return TYPE_E_ELEMENTNOTFOUND
;
8077 VariantInit(pVarVal
);
8078 VariantCopy(pVarVal
, &pCData
->data
);
8083 /* ITypeInfo2::GetParamCustData
8085 * Gets the custom data
8087 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8094 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8095 TLBCustData
*pCData
;
8096 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8098 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8099 debugstr_guid(guid
), pVarVal
);
8101 if(indexFunc
>= This
->cFuncs
)
8102 return TYPE_E_ELEMENTNOTFOUND
;
8104 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8105 return TYPE_E_ELEMENTNOTFOUND
;
8107 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8109 return TYPE_E_ELEMENTNOTFOUND
;
8111 VariantInit(pVarVal
);
8112 VariantCopy(pVarVal
, &pCData
->data
);
8117 /* ITypeInfo2::GetVarCustData
8119 * Gets the custom data
8121 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8127 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8128 TLBCustData
*pCData
;
8129 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8131 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8133 if(index
>= This
->cVars
)
8134 return TYPE_E_ELEMENTNOTFOUND
;
8136 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8138 return TYPE_E_ELEMENTNOTFOUND
;
8140 VariantInit(pVarVal
);
8141 VariantCopy(pVarVal
, &pCData
->data
);
8146 /* ITypeInfo2::GetImplCustData
8148 * Gets the custom data
8150 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8156 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8157 TLBCustData
*pCData
;
8158 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8160 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8162 if(index
>= This
->cImplTypes
)
8163 return TYPE_E_ELEMENTNOTFOUND
;
8165 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8167 return TYPE_E_ELEMENTNOTFOUND
;
8169 VariantInit(pVarVal
);
8170 VariantCopy(pVarVal
, &pCData
->data
);
8175 /* ITypeInfo2::GetDocumentation2
8177 * Retrieves the documentation string, the complete Help file name and path,
8178 * the localization context to use, and the context ID for the library Help
8179 * topic in the Help file.
8182 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8186 BSTR
*pbstrHelpString
,
8187 DWORD
*pdwHelpStringContext
,
8188 BSTR
*pbstrHelpStringDll
)
8190 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8191 const TLBFuncDesc
*pFDesc
;
8192 const TLBVarDesc
*pVDesc
;
8193 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8194 "HelpStringContext(%p) HelpStringDll(%p)\n",
8195 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8196 pbstrHelpStringDll
);
8197 /* the help string should be obtained from the helpstringdll,
8198 * using the _DLLGetDocumentation function, based on the supplied
8199 * lcid. Nice to do sometime...
8201 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8203 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8204 if(pdwHelpStringContext
)
8205 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8206 if(pbstrHelpStringDll
)
8207 *pbstrHelpStringDll
=
8208 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8210 }else {/* for a member */
8211 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
8214 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8215 if(pdwHelpStringContext
)
8216 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8217 if(pbstrHelpStringDll
)
8218 *pbstrHelpStringDll
=
8219 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8222 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8225 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8226 if(pdwHelpStringContext
)
8227 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8228 if(pbstrHelpStringDll
)
8229 *pbstrHelpStringDll
=
8230 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8234 return TYPE_E_ELEMENTNOTFOUND
;
8237 /* ITypeInfo2::GetAllCustData
8239 * Gets all custom data items for the Type info.
8242 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8244 CUSTDATA
*pCustData
)
8246 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8248 TRACE("%p %p\n", This
, pCustData
);
8250 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8253 /* ITypeInfo2::GetAllFuncCustData
8255 * Gets all custom data items for the specified Function
8258 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8261 CUSTDATA
*pCustData
)
8263 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8264 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8266 TRACE("%p %u %p\n", This
, index
, pCustData
);
8268 if(index
>= This
->cFuncs
)
8269 return TYPE_E_ELEMENTNOTFOUND
;
8271 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8274 /* ITypeInfo2::GetAllParamCustData
8276 * Gets all custom data items for the Functions
8279 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8280 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8282 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8283 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8285 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8287 if(indexFunc
>= This
->cFuncs
)
8288 return TYPE_E_ELEMENTNOTFOUND
;
8290 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8291 return TYPE_E_ELEMENTNOTFOUND
;
8293 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8296 /* ITypeInfo2::GetAllVarCustData
8298 * Gets all custom data items for the specified Variable
8301 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8302 UINT index
, CUSTDATA
*pCustData
)
8304 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8305 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8307 TRACE("%p %u %p\n", This
, index
, pCustData
);
8309 if(index
>= This
->cVars
)
8310 return TYPE_E_ELEMENTNOTFOUND
;
8312 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8315 /* ITypeInfo2::GetAllImplCustData
8317 * Gets all custom data items for the specified implementation type
8320 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8323 CUSTDATA
*pCustData
)
8325 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8326 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8328 TRACE("%p %u %p\n", This
, index
, pCustData
);
8330 if(index
>= This
->cImplTypes
)
8331 return TYPE_E_ELEMENTNOTFOUND
;
8333 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8336 static const ITypeInfo2Vtbl tinfvt
=
8339 ITypeInfo_fnQueryInterface
,
8341 ITypeInfo_fnRelease
,
8343 ITypeInfo_fnGetTypeAttr
,
8344 ITypeInfo_fnGetTypeComp
,
8345 ITypeInfo_fnGetFuncDesc
,
8346 ITypeInfo_fnGetVarDesc
,
8347 ITypeInfo_fnGetNames
,
8348 ITypeInfo_fnGetRefTypeOfImplType
,
8349 ITypeInfo_fnGetImplTypeFlags
,
8350 ITypeInfo_fnGetIDsOfNames
,
8352 ITypeInfo_fnGetDocumentation
,
8353 ITypeInfo_fnGetDllEntry
,
8354 ITypeInfo_fnGetRefTypeInfo
,
8355 ITypeInfo_fnAddressOfMember
,
8356 ITypeInfo_fnCreateInstance
,
8357 ITypeInfo_fnGetMops
,
8358 ITypeInfo_fnGetContainingTypeLib
,
8359 ITypeInfo_fnReleaseTypeAttr
,
8360 ITypeInfo_fnReleaseFuncDesc
,
8361 ITypeInfo_fnReleaseVarDesc
,
8363 ITypeInfo2_fnGetTypeKind
,
8364 ITypeInfo2_fnGetTypeFlags
,
8365 ITypeInfo2_fnGetFuncIndexOfMemId
,
8366 ITypeInfo2_fnGetVarIndexOfMemId
,
8367 ITypeInfo2_fnGetCustData
,
8368 ITypeInfo2_fnGetFuncCustData
,
8369 ITypeInfo2_fnGetParamCustData
,
8370 ITypeInfo2_fnGetVarCustData
,
8371 ITypeInfo2_fnGetImplTypeCustData
,
8372 ITypeInfo2_fnGetDocumentation2
,
8373 ITypeInfo2_fnGetAllCustData
,
8374 ITypeInfo2_fnGetAllFuncCustData
,
8375 ITypeInfo2_fnGetAllParamCustData
,
8376 ITypeInfo2_fnGetAllVarCustData
,
8377 ITypeInfo2_fnGetAllImplTypeCustData
,
8380 /******************************************************************************
8381 * CreateDispTypeInfo [OLEAUT32.31]
8383 * Build type information for an object so it can be called through an
8384 * IDispatch interface.
8387 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8388 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8391 * This call allows an objects methods to be accessed through IDispatch, by
8392 * building an ITypeInfo object that IDispatch can use to call through.
8394 HRESULT WINAPI
CreateDispTypeInfo(
8395 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8396 LCID lcid
, /* [I] Locale Id */
8397 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8399 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8400 ITypeLibImpl
*pTypeLibImpl
;
8401 unsigned int param
, func
;
8402 TLBFuncDesc
*pFuncDesc
;
8406 pTypeLibImpl
= TypeLibImpl_Constructor();
8407 if (!pTypeLibImpl
) return E_FAIL
;
8409 pTypeLibImpl
->TypeInfoCount
= 2;
8410 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8412 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8413 pTIIface
->pTypeLib
= pTypeLibImpl
;
8414 pTIIface
->index
= 0;
8415 pTIIface
->Name
= NULL
;
8416 pTIIface
->dwHelpContext
= -1;
8417 pTIIface
->guid
= NULL
;
8418 pTIIface
->lcid
= lcid
;
8419 pTIIface
->typekind
= TKIND_INTERFACE
;
8420 pTIIface
->wMajorVerNum
= 0;
8421 pTIIface
->wMinorVerNum
= 0;
8422 pTIIface
->cbAlignment
= 2;
8423 pTIIface
->cbSizeInstance
= -1;
8424 pTIIface
->cbSizeVft
= -1;
8425 pTIIface
->cFuncs
= 0;
8426 pTIIface
->cImplTypes
= 0;
8427 pTIIface
->cVars
= 0;
8428 pTIIface
->wTypeFlags
= 0;
8429 pTIIface
->hreftype
= 0;
8431 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8432 pFuncDesc
= pTIIface
->funcdescs
;
8433 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8434 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8435 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8436 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8437 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8438 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8439 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8440 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8441 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8442 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8443 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8444 pFuncDesc
->funcdesc
.cScodes
= 0;
8445 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8446 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8447 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8448 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8449 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8450 md
->cArgs
* sizeof(ELEMDESC
));
8451 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8452 for(param
= 0; param
< md
->cArgs
; param
++) {
8453 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8454 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8456 pFuncDesc
->helpcontext
= 0;
8457 pFuncDesc
->HelpStringContext
= 0;
8458 pFuncDesc
->HelpString
= NULL
;
8459 pFuncDesc
->Entry
= NULL
;
8460 list_init(&pFuncDesc
->custdata_list
);
8465 dump_TypeInfo(pTIIface
);
8467 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8468 pTIClass
->pTypeLib
= pTypeLibImpl
;
8469 pTIClass
->index
= 1;
8470 pTIClass
->Name
= NULL
;
8471 pTIClass
->dwHelpContext
= -1;
8472 pTIClass
->guid
= NULL
;
8473 pTIClass
->lcid
= lcid
;
8474 pTIClass
->typekind
= TKIND_COCLASS
;
8475 pTIClass
->wMajorVerNum
= 0;
8476 pTIClass
->wMinorVerNum
= 0;
8477 pTIClass
->cbAlignment
= 2;
8478 pTIClass
->cbSizeInstance
= -1;
8479 pTIClass
->cbSizeVft
= -1;
8480 pTIClass
->cFuncs
= 0;
8481 pTIClass
->cImplTypes
= 1;
8482 pTIClass
->cVars
= 0;
8483 pTIClass
->wTypeFlags
= 0;
8484 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8486 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8488 ref
= heap_alloc_zero(sizeof(*ref
));
8489 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8490 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8492 dump_TypeInfo(pTIClass
);
8494 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8496 ITypeInfo_AddRef(*pptinfo
);
8497 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8503 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8505 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8507 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8510 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8512 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8514 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8517 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8519 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8521 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8524 static HRESULT WINAPI
ITypeComp_fnBind(
8529 ITypeInfo
** ppTInfo
,
8530 DESCKIND
* pDescKind
,
8533 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8534 const TLBFuncDesc
*pFDesc
;
8535 const TLBVarDesc
*pVDesc
;
8536 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8539 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8541 *pDescKind
= DESCKIND_NONE
;
8542 pBindPtr
->lpfuncdesc
= NULL
;
8545 for(fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8546 pFDesc
= &This
->funcdescs
[fdc
];
8547 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8548 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8551 /* name found, but wrong flags */
8552 hr
= TYPE_E_TYPEMISMATCH
;
8556 if (fdc
< This
->cFuncs
)
8558 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8560 &pBindPtr
->lpfuncdesc
,
8561 This
->typekind
== TKIND_DISPATCH
);
8564 *pDescKind
= DESCKIND_FUNCDESC
;
8565 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8566 ITypeInfo_AddRef(*ppTInfo
);
8569 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, szName
);
8571 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8574 *pDescKind
= DESCKIND_VARDESC
;
8575 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8576 ITypeInfo_AddRef(*ppTInfo
);
8581 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8582 /* recursive search */
8586 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8589 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8590 ITypeInfo_Release(pTInfo
);
8594 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8595 ITypeComp_Release(pTComp
);
8596 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8597 This
->typekind
== TKIND_DISPATCH
)
8599 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8600 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8601 SysFreeString((BSTR
)tmp
);
8605 WARN("Could not search inherited interface!\n");
8607 if (hr
== DISP_E_MEMBERNOTFOUND
)
8609 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8613 static HRESULT WINAPI
ITypeComp_fnBindType(
8617 ITypeInfo
** ppTInfo
,
8618 ITypeComp
** ppTComp
)
8620 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8622 /* strange behaviour (does nothing) but like the
8625 if (!ppTInfo
|| !ppTComp
)
8634 static const ITypeCompVtbl tcompvt
=
8637 ITypeComp_fnQueryInterface
,
8639 ITypeComp_fnRelease
,
8642 ITypeComp_fnBindType
8645 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8646 ICreateTypeLib2
** ppctlib
)
8651 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8653 if (!szFile
) return E_INVALIDARG
;
8655 This
= TypeLibImpl_Constructor();
8657 return E_OUTOFMEMORY
;
8659 This
->lcid
= GetSystemDefaultLCID();
8660 This
->syskind
= syskind
;
8661 This
->ptr_size
= get_ptr_size(syskind
);
8663 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8665 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8666 return E_OUTOFMEMORY
;
8668 lstrcpyW(This
->path
, szFile
);
8670 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8671 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8675 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8676 REFIID riid
, void **object
)
8678 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8680 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8683 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8685 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8687 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8690 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8692 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8694 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8697 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8698 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8700 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8701 ITypeInfoImpl
*info
;
8704 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8706 if (!ctinfo
|| !name
)
8707 return E_INVALIDARG
;
8709 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8711 return TYPE_E_NAMECONFLICT
;
8713 if (This
->typeinfos
)
8714 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8715 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8717 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8719 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8721 info
->pTypeLib
= This
;
8722 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8723 info
->index
= This
->TypeInfoCount
;
8724 info
->typekind
= kind
;
8725 info
->cbAlignment
= 4;
8727 switch(info
->typekind
) {
8729 case TKIND_INTERFACE
:
8730 case TKIND_DISPATCH
:
8732 info
->cbSizeInstance
= This
->ptr_size
;
8736 info
->cbSizeInstance
= 0;
8739 info
->cbSizeInstance
= 2;
8742 info
->cbSizeInstance
= -0x75;
8745 FIXME("unrecognized typekind %d\n", info
->typekind
);
8746 info
->cbSizeInstance
= 0xdeadbeef;
8750 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8751 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8753 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8757 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8759 ++This
->TypeInfoCount
;
8764 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8767 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8769 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8772 return E_INVALIDARG
;
8774 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8779 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8780 WORD majorVerNum
, WORD minorVerNum
)
8782 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8784 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8786 This
->ver_major
= majorVerNum
;
8787 This
->ver_minor
= minorVerNum
;
8792 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8795 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8797 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8799 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8804 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8807 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8809 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8812 return E_INVALIDARG
;
8814 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8819 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8820 LPOLESTR helpFileName
)
8822 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8824 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8827 return E_INVALIDARG
;
8829 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8834 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8837 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8839 TRACE("%p %d\n", This
, helpContext
);
8841 This
->dwHelpContext
= helpContext
;
8846 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8849 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8851 TRACE("%p %x\n", This
, lcid
);
8853 This
->set_lcid
= lcid
;
8858 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8861 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8863 TRACE("%p %x\n", This
, libFlags
);
8865 This
->libflags
= libFlags
;
8870 typedef struct tagWMSFT_SegContents
{
8873 } WMSFT_SegContents
;
8875 typedef struct tagWMSFT_TLBFile
{
8877 WMSFT_SegContents typeinfo_seg
;
8878 WMSFT_SegContents impfile_seg
;
8879 WMSFT_SegContents impinfo_seg
;
8880 WMSFT_SegContents ref_seg
;
8881 WMSFT_SegContents guidhash_seg
;
8882 WMSFT_SegContents guid_seg
;
8883 WMSFT_SegContents namehash_seg
;
8884 WMSFT_SegContents name_seg
;
8885 WMSFT_SegContents string_seg
;
8886 WMSFT_SegContents typdesc_seg
;
8887 WMSFT_SegContents arraydesc_seg
;
8888 WMSFT_SegContents custdata_seg
;
8889 WMSFT_SegContents cdguids_seg
;
8891 WMSFT_SegContents aux_seg
;
8894 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8895 WMSFT_TLBFile
*file
)
8901 file
->string_seg
.len
= 0;
8902 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8905 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8907 return E_UNEXPECTED
;
8909 size
+= sizeof(INT16
);
8911 size
= (size
+ 4) & ~0x3;
8915 file
->string_seg
.len
+= size
;
8917 /* temporarily use str->offset to store the length of the aligned,
8918 * converted string */
8922 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8925 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8928 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8929 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8931 heap_free(file
->string_seg
.data
);
8932 return E_UNEXPECTED
;
8935 *((INT16
*)data
) = size
;
8937 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8941 str
->offset
= last_offs
;
8948 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8949 WMSFT_TLBFile
*file
)
8954 MSFT_NameIntro
*last_intro
= NULL
;
8956 file
->header
.nametablecount
= 0;
8957 file
->header
.nametablechars
= 0;
8959 file
->name_seg
.len
= 0;
8960 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8963 size
= strlenW(str
->str
);
8964 file
->header
.nametablechars
+= size
;
8965 file
->header
.nametablecount
++;
8967 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8969 return E_UNEXPECTED
;
8971 size
+= sizeof(MSFT_NameIntro
);
8973 size
= (size
+ 4) & ~0x3;
8977 file
->name_seg
.len
+= size
;
8979 /* temporarily use str->offset to store the length of the aligned,
8980 * converted string */
8984 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8985 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
8988 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8990 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8992 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8993 data
+ sizeof(MSFT_NameIntro
),
8994 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8996 heap_free(file
->name_seg
.data
);
8997 return E_UNEXPECTED
;
8999 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9001 intro
->hreftype
= -1; /* TODO? */
9002 intro
->namelen
= size
& 0xFF;
9003 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9004 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9005 intro
->namelen
|= hash
<< 16;
9006 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9007 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9009 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9010 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9012 /* update str->offset to actual value to use in other
9013 * compilation functions that require positions within
9014 * the string table */
9018 str
->offset
= last_offs
;
9023 last_intro
->hreftype
= 0; /* last one is 0? */
9028 static inline int hash_guid(GUID
*guid
)
9032 for (i
= 0; i
< 8; i
++)
9033 hash
^= ((const short *)guid
)[i
];
9038 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9041 MSFT_GuidEntry
*entry
;
9043 int hash_key
, *guidhashtab
;
9045 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9046 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9048 entry
= file
->guid_seg
.data
;
9050 guidhashtab
= file
->guidhash_seg
.data
;
9051 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9052 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9053 entry
->hreftype
= guid
->hreftype
;
9055 hash_key
= hash_guid(&guid
->guid
);
9056 entry
->next_hash
= guidhashtab
[hash_key
];
9057 guidhashtab
[hash_key
] = offs
;
9059 guid
->offset
= offs
;
9060 offs
+= sizeof(MSFT_GuidEntry
);
9067 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9070 VARTYPE arg_type
= V_VT(value
);
9073 DWORD ret
= file
->custdata_seg
.len
;
9075 if(arg_type
== VT_INT
)
9077 if(arg_type
== VT_UINT
)
9081 if(V_VT(value
) != arg_type
) {
9082 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9084 ERR("VariantChangeType failed: %08x\n", hres
);
9089 /* Check if default value can be stored in-place */
9094 if(V_UI4(&v
) > 0x3ffffff)
9107 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9110 /* have to allocate space in custdata_seg */
9119 /* Construct the data to be allocated */
9122 if(file
->custdata_seg
.data
){
9123 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9124 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9125 file
->custdata_seg
.len
+= sizeof(int) * 2;
9127 file
->custdata_seg
.len
= sizeof(int) * 2;
9128 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9131 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9132 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9134 /* TODO: Check if the encoded data is already present in custdata_seg */
9140 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9143 if(file
->custdata_seg
.data
){
9144 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9145 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9146 file
->custdata_seg
.len
+= len
;
9148 file
->custdata_seg
.len
= len
;
9149 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9152 *((unsigned short *)data
) = V_VT(value
);
9153 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9154 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9155 if(V_BSTR(&v
)[i
] <= 0x7f)
9156 data
[i
+6] = V_BSTR(&v
)[i
];
9160 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9161 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9164 /* TODO: Check if the encoded data is already present in custdata_seg */
9169 FIXME("Argument type not yet handled\n");
9174 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9176 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9178 DWORD offs
= file
->arraydesc_seg
.len
;
9182 /* TODO: we should check for duplicates, but that's harder because each
9183 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9184 * at the library-level) */
9186 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9187 if(!file
->arraydesc_seg
.data
)
9188 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9190 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9191 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9193 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9194 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9195 for(i
= 0; i
< desc
->cDims
; ++i
){
9196 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9197 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9203 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9209 VARTYPE vt
, subtype
;
9220 vt
= desc
->vt
& VT_TYPEMASK
;
9222 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9224 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9225 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9227 *out_size
+= 2 * sizeof(DWORD
);
9228 }else if(vt
== VT_CARRAY
){
9229 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9230 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9232 }else if(vt
== VT_USERDEFINED
){
9233 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9234 encoded
[1] = desc
->u
.hreftype
;
9235 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9237 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9255 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9258 data
= file
->typdesc_seg
.data
;
9259 while(offs
< file
->typdesc_seg
.len
){
9260 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9262 offs
+= sizeof(encoded
);
9265 file
->typdesc_seg
.len
+= sizeof(encoded
);
9266 if(!file
->typdesc_seg
.data
)
9267 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9269 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9271 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9276 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9278 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9279 DWORD ret
= cdguids_seg
->len
, offs
;
9280 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
9283 if(list_empty(custdata_list
))
9286 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9287 if(!cdguids_seg
->data
){
9288 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9290 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9292 offs
= ret
+ sizeof(MSFT_CDGuid
);
9293 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9294 cdguid
->GuidOffset
= cd
->guid
->offset
;
9295 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9296 cdguid
->next
= offs
;
9297 offs
+= sizeof(MSFT_CDGuid
);
9307 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9308 WMSFT_TLBFile
*file
)
9310 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9311 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9312 MSFT_VarRecord
*varrecord
;
9313 MSFT_FuncRecord
*funcrecord
;
9315 DWORD
*name
, *offsets
, offs
;
9317 for(i
= 0; i
< info
->cFuncs
; ++i
){
9318 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9320 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9322 /* optional fields */
9323 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9324 if(!list_empty(&desc
->custdata_list
))
9325 recorded_size
+= 7 * sizeof(INT
);
9326 else if(desc
->HelpStringContext
!= 0)
9327 recorded_size
+= 6 * sizeof(INT
);
9329 else if(desc
->Entry
)
9330 recorded_size
+= 3 * sizeof(INT
);
9331 else if(desc
->HelpString
)
9332 recorded_size
+= 2 * sizeof(INT
);
9333 else if(desc
->helpcontext
)
9334 recorded_size
+= sizeof(INT
);
9336 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9338 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9339 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9340 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9345 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9348 for(i
= 0; i
< info
->cVars
; ++i
){
9349 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9351 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9353 /* optional fields */
9354 if(desc
->HelpStringContext
!= 0)
9355 recorded_size
+= 5 * sizeof(INT
);
9356 else if(!list_empty(&desc
->custdata_list
))
9357 recorded_size
+= 4 * sizeof(INT
);
9359 else if(desc
->HelpString
)
9360 recorded_size
+= 2 * sizeof(INT
);
9361 else if(desc
->HelpContext
!= 0)
9362 recorded_size
+= sizeof(INT
);
9364 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9367 if(!recorded_size
&& !extra_size
)
9370 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9372 aux_seg
->len
+= recorded_size
+ extra_size
;
9374 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9377 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9379 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9381 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9383 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9386 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9387 for(i
= 0; i
< info
->cFuncs
; ++i
){
9388 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9389 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9391 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9392 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9393 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9394 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9397 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9402 * ^has_param_defaults
9403 * ^oEntry_is_intresource
9405 funcrecord
->FKCCIC
=
9406 desc
->funcdesc
.funckind
|
9407 (desc
->funcdesc
.invkind
<< 3) |
9408 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9409 (desc
->funcdesc
.callconv
<< 8);
9411 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9412 funcrecord
->FKCCIC
|= 0x2000;
9414 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9415 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9416 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9417 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9420 if(paramdefault_size
> 0)
9421 funcrecord
->FKCCIC
|= 0x1000;
9423 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9424 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9426 /* optional fields */
9428 if(!list_empty(&desc
->custdata_list
)){
9429 size
+= 7 * sizeof(INT
);
9430 funcrecord
->HelpContext
= desc
->helpcontext
;
9431 if(desc
->HelpString
)
9432 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9434 funcrecord
->oHelpString
= -1;
9436 funcrecord
->oEntry
= -1;
9437 else if(IS_INTRESOURCE(desc
->Entry
))
9438 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9440 funcrecord
->oEntry
= desc
->Entry
->offset
;
9441 funcrecord
->res9
= -1;
9442 funcrecord
->resA
= -1;
9443 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9444 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9445 }else if(desc
->HelpStringContext
!= 0){
9446 size
+= 6 * sizeof(INT
);
9447 funcrecord
->HelpContext
= desc
->helpcontext
;
9448 if(desc
->HelpString
)
9449 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9451 funcrecord
->oHelpString
= -1;
9453 funcrecord
->oEntry
= -1;
9454 else if(IS_INTRESOURCE(desc
->Entry
))
9455 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9457 funcrecord
->oEntry
= desc
->Entry
->offset
;
9458 funcrecord
->res9
= -1;
9459 funcrecord
->resA
= -1;
9460 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9461 }else if(desc
->Entry
){
9462 size
+= 3 * sizeof(INT
);
9463 funcrecord
->HelpContext
= desc
->helpcontext
;
9464 if(desc
->HelpString
)
9465 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9467 funcrecord
->oHelpString
= -1;
9469 funcrecord
->oEntry
= -1;
9470 else if(IS_INTRESOURCE(desc
->Entry
))
9471 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9473 funcrecord
->oEntry
= desc
->Entry
->offset
;
9474 }else if(desc
->HelpString
){
9475 size
+= 2 * sizeof(INT
);
9476 funcrecord
->HelpContext
= desc
->helpcontext
;
9477 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9478 }else if(desc
->helpcontext
){
9479 size
+= sizeof(INT
);
9480 funcrecord
->HelpContext
= desc
->helpcontext
;
9483 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9484 size
+= paramdefault_size
;
9486 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9487 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9489 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9490 if(desc
->pParamDesc
[j
].Name
)
9491 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9494 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9496 if(paramdefault_size
){
9497 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9498 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9499 else if(paramdefault_size
)
9504 size
+= sizeof(MSFT_ParameterInfo
);
9507 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9513 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9516 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9517 for(i
= 0; i
< info
->cVars
; ++i
){
9518 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9519 DWORD size
= 5 * sizeof(INT
);
9521 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9522 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9523 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9524 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9526 if(desc
->vardesc
.varkind
== VAR_CONST
){
9527 varrecord
->vardescsize
+= sizeof(VARIANT
);
9528 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9530 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9533 if(desc
->HelpStringContext
!= 0){
9534 size
+= 5 * sizeof(INT
);
9535 varrecord
->HelpContext
= desc
->HelpContext
;
9536 if(desc
->HelpString
)
9537 varrecord
->HelpString
= desc
->HelpString
->offset
;
9539 varrecord
->HelpString
= -1;
9540 varrecord
->res9
= -1;
9541 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9542 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9543 }else if(!list_empty(&desc
->custdata_list
)){
9544 size
+= 4 * sizeof(INT
);
9545 varrecord
->HelpContext
= desc
->HelpContext
;
9546 if(desc
->HelpString
)
9547 varrecord
->HelpString
= desc
->HelpString
->offset
;
9549 varrecord
->HelpString
= -1;
9550 varrecord
->res9
= -1;
9551 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9552 }else if(desc
->HelpString
){
9553 size
+= 2 * sizeof(INT
);
9554 varrecord
->HelpContext
= desc
->HelpContext
;
9555 if(desc
->HelpString
)
9556 varrecord
->HelpString
= desc
->HelpString
->offset
;
9558 varrecord
->HelpString
= -1;
9559 }else if(desc
->HelpContext
!= 0){
9560 size
+= sizeof(INT
);
9561 varrecord
->HelpContext
= desc
->HelpContext
;
9564 varrecord
->Info
= size
| (i
<< 16);
9570 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9573 memid
= (MEMBERID
*)varrecord
;
9574 for(i
= 0; i
< info
->cFuncs
; ++i
){
9575 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9576 *memid
= desc
->funcdesc
.memid
;
9579 for(i
= 0; i
< info
->cVars
; ++i
){
9580 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9581 *memid
= desc
->vardesc
.memid
;
9585 name
= (UINT
*)memid
;
9586 for(i
= 0; i
< info
->cFuncs
; ++i
){
9587 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9589 *name
= desc
->Name
->offset
;
9594 for(i
= 0; i
< info
->cVars
; ++i
){
9595 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9597 *name
= desc
->Name
->offset
;
9606 typedef struct tagWMSFT_RefChunk
{
9613 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9615 DWORD offs
= file
->ref_seg
.len
, i
;
9616 WMSFT_RefChunk
*chunk
;
9618 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9619 if(!file
->ref_seg
.data
)
9620 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9622 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9624 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9626 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9627 chunk
->href
= info
->impltypes
[i
].hRef
;
9628 chunk
->res04
= info
->impltypes
[i
].implflags
;
9630 if(i
< info
->cImplTypes
- 1)
9631 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9640 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9644 size
= sizeof(MSFT_TypeInfoBase
);
9647 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9648 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9649 base
->typekind
= TKIND_DISPATCH
;
9651 base
->typekind
= info
->typekind
;
9652 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9653 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9654 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9659 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9665 base
->posguid
= info
->guid
->offset
;
9668 base
->flags
= info
->wTypeFlags
;
9670 base
->NameOffset
= info
->Name
->offset
;
9672 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9673 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9675 base
->NameOffset
= -1;
9677 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9679 base
->docstringoffs
= info
->DocString
->offset
;
9681 base
->docstringoffs
= -1;
9682 base
->helpstringcontext
= info
->dwHelpStringContext
;
9683 base
->helpcontext
= info
->dwHelpContext
;
9684 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9685 base
->cImplTypes
= info
->cImplTypes
;
9686 base
->cbSizeVft
= info
->cbSizeVft
;
9687 base
->size
= info
->cbSizeInstance
;
9688 if(info
->typekind
== TKIND_COCLASS
){
9689 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9690 }else if(info
->typekind
== TKIND_ALIAS
){
9691 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9692 }else if(info
->typekind
== TKIND_MODULE
){
9694 base
->datatype1
= info
->DllName
->offset
;
9696 base
->datatype1
= -1;
9698 if(info
->cImplTypes
> 0)
9699 base
->datatype1
= info
->impltypes
[0].hRef
;
9701 base
->datatype1
= -1;
9703 base
->datatype2
= index
; /* FIXME: i think there's more here */
9711 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9715 file
->typeinfo_seg
.len
= 0;
9716 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9717 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9718 *junk
= file
->typeinfo_seg
.len
;
9720 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9723 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9724 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9726 file
->aux_seg
.len
= 0;
9727 file
->aux_seg
.data
= NULL
;
9729 file
->typeinfo_seg
.len
= 0;
9730 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9731 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9732 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9733 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9737 typedef struct tagWMSFT_ImpFile
{
9743 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9746 WMSFT_ImpFile
*impfile
;
9748 DWORD last_offs
= 0;
9750 file
->impfile_seg
.len
= 0;
9751 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9755 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9759 path
= implib
->name
;
9760 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9762 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9765 size
+= sizeof(INT16
);
9767 size
= (size
+ 4) & ~0x3;
9771 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9774 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9776 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9777 int strlen
= 0, size
;
9779 impfile
= (WMSFT_ImpFile
*)data
;
9780 impfile
->guid_offs
= implib
->guid
->offset
;
9781 impfile
->lcid
= implib
->lcid
;
9782 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9784 data
+= sizeof(WMSFT_ImpFile
);
9787 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9791 path
= implib
->name
;
9792 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9793 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9795 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9798 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9800 size
= strlen
+ sizeof(INT16
);
9802 size
= (size
+ 4) & ~0x3;
9805 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9808 implib
->offset
= last_offs
;
9809 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9813 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9816 TLBRefType
*ref_type
;
9819 WMSFT_compile_impfile(This
, file
);
9821 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9822 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9824 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9825 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9826 if(ref_type
->index
== TLB_REF_USE_GUID
){
9827 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9828 info
->oGuid
= ref_type
->guid
->offset
;
9830 info
->oGuid
= ref_type
->index
;
9831 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9837 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9839 file
->guidhash_seg
.len
= 0x80;
9840 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9841 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9844 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9846 file
->namehash_seg
.len
= 0x200;
9847 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9848 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9851 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9853 if(contents
&& contents
->len
){
9854 segdir
->offset
= *running_offset
;
9855 segdir
->length
= contents
->len
;
9856 *running_offset
+= segdir
->length
;
9858 segdir
->offset
= -1;
9862 /* TODO: do these ever change? */
9864 segdir
->res0c
= 0xf;
9867 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9871 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9874 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9878 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9880 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9881 base
->memoffset
+= file_len
;
9888 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9890 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9891 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9892 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9893 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9894 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9895 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9896 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9897 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9898 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9899 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9900 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9901 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9902 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9903 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9906 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9908 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9910 DWORD written
, junk_size
, junk_offs
, running_offset
;
9917 TRACE("%p\n", This
);
9919 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
9920 if(This
->typeinfos
[i
]->needs_layout
)
9921 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
9923 memset(&file
, 0, sizeof(file
));
9925 file
.header
.magic1
= 0x5446534D;
9926 file
.header
.magic2
= 0x00010002;
9927 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9928 file
.header
.lcid2
= This
->set_lcid
;
9929 file
.header
.varflags
= 0x40 | This
->syskind
;
9931 file
.header
.varflags
|= 0x10;
9932 if (This
->HelpStringDll
)
9933 file
.header
.varflags
|= HELPDLLFLAG
;
9934 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
9935 file
.header
.flags
= This
->libflags
;
9936 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9937 file
.header
.helpcontext
= This
->dwHelpContext
;
9938 file
.header
.res44
= 0x20;
9939 file
.header
.res48
= 0x80;
9940 file
.header
.dispatchpos
= This
->dispatch_href
;
9942 WMSFT_compile_namehash(This
, &file
);
9943 /* do name and string compilation to get offsets for other compilations */
9944 hres
= WMSFT_compile_names(This
, &file
);
9946 WMSFT_free_file(&file
);
9950 hres
= WMSFT_compile_strings(This
, &file
);
9952 WMSFT_free_file(&file
);
9956 WMSFT_compile_guidhash(This
, &file
);
9957 hres
= WMSFT_compile_guids(This
, &file
);
9959 WMSFT_free_file(&file
);
9964 file
.header
.helpfile
= This
->HelpFile
->offset
;
9966 file
.header
.helpfile
= -1;
9969 file
.header
.helpstring
= This
->DocString
->offset
;
9971 file
.header
.helpstring
= -1;
9973 /* do some more segment compilation */
9974 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9975 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9978 file
.header
.NameOffset
= This
->Name
->offset
;
9980 file
.header
.NameOffset
= -1;
9982 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
9985 file
.header
.posguid
= This
->guid
->offset
;
9987 file
.header
.posguid
= -1;
9989 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9990 if(file
.header
.varflags
& HELPDLLFLAG
)
9991 junk_size
+= sizeof(DWORD
);
9993 junk
= heap_alloc_zero(junk_size
);
9994 if(file
.header
.varflags
& HELPDLLFLAG
){
9995 *junk
= This
->HelpStringDll
->offset
;
10004 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10005 WMSFT_compile_impinfo(This
, &file
);
10007 running_offset
= 0;
10009 TRACE("header at: 0x%x\n", running_offset
);
10010 running_offset
+= sizeof(file
.header
);
10012 TRACE("junk at: 0x%x\n", running_offset
);
10013 running_offset
+= junk_size
;
10015 TRACE("segdir at: 0x%x\n", running_offset
);
10016 running_offset
+= sizeof(file
.segdir
);
10018 TRACE("typeinfo at: 0x%x\n", running_offset
);
10019 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10021 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10022 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10024 TRACE("guidtab at: 0x%x\n", running_offset
);
10025 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10027 TRACE("reftab at: 0x%x\n", running_offset
);
10028 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10030 TRACE("impinfo at: 0x%x\n", running_offset
);
10031 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10033 TRACE("impfiles at: 0x%x\n", running_offset
);
10034 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10036 TRACE("namehashtab at: 0x%x\n", running_offset
);
10037 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10039 TRACE("nametab at: 0x%x\n", running_offset
);
10040 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10042 TRACE("stringtab at: 0x%x\n", running_offset
);
10043 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10045 TRACE("typdesc at: 0x%x\n", running_offset
);
10046 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10048 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10049 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10051 TRACE("custdata at: 0x%x\n", running_offset
);
10052 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10054 TRACE("cdguids at: 0x%x\n", running_offset
);
10055 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10057 TRACE("res0e at: 0x%x\n", running_offset
);
10058 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10060 TRACE("res0f at: 0x%x\n", running_offset
);
10061 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10063 TRACE("aux_seg at: 0x%x\n", running_offset
);
10065 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10067 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10068 FILE_ATTRIBUTE_NORMAL
, 0);
10069 if (outfile
== INVALID_HANDLE_VALUE
){
10070 WMSFT_free_file(&file
);
10072 return TYPE_E_IOERROR
;
10075 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10077 WMSFT_free_file(&file
);
10078 CloseHandle(outfile
);
10080 return TYPE_E_IOERROR
;
10083 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10086 WMSFT_free_file(&file
);
10087 CloseHandle(outfile
);
10088 return TYPE_E_IOERROR
;
10091 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10093 WMSFT_free_file(&file
);
10094 CloseHandle(outfile
);
10095 return TYPE_E_IOERROR
;
10098 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10099 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10100 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10101 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10102 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10103 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10104 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10105 WMSFT_write_segment(outfile
, &file
.name_seg
);
10106 WMSFT_write_segment(outfile
, &file
.string_seg
);
10107 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10108 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10109 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10110 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10111 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10113 WMSFT_free_file(&file
);
10115 CloseHandle(outfile
);
10120 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10123 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10124 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10128 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10129 REFGUID guid
, VARIANT
*varVal
)
10131 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10132 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
10136 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10137 ULONG helpStringContext
)
10139 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10140 FIXME("%p %u - stub\n", This
, helpStringContext
);
10144 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10147 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10148 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10151 return E_INVALIDARG
;
10153 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10158 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10159 ICreateTypeLib2_fnQueryInterface
,
10160 ICreateTypeLib2_fnAddRef
,
10161 ICreateTypeLib2_fnRelease
,
10162 ICreateTypeLib2_fnCreateTypeInfo
,
10163 ICreateTypeLib2_fnSetName
,
10164 ICreateTypeLib2_fnSetVersion
,
10165 ICreateTypeLib2_fnSetGuid
,
10166 ICreateTypeLib2_fnSetDocString
,
10167 ICreateTypeLib2_fnSetHelpFileName
,
10168 ICreateTypeLib2_fnSetHelpContext
,
10169 ICreateTypeLib2_fnSetLcid
,
10170 ICreateTypeLib2_fnSetLibFlags
,
10171 ICreateTypeLib2_fnSaveAllChanges
,
10172 ICreateTypeLib2_fnDeleteTypeInfo
,
10173 ICreateTypeLib2_fnSetCustData
,
10174 ICreateTypeLib2_fnSetHelpStringContext
,
10175 ICreateTypeLib2_fnSetHelpStringDll
10178 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10179 REFIID riid
, void **object
)
10181 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10183 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10186 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10188 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10190 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10193 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10195 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10197 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10200 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10203 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10205 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10207 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10212 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10215 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10219 TRACE("%p %x\n", This
, typeFlags
);
10221 if (typeFlags
& TYPEFLAG_FDUAL
) {
10222 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10224 ITypeInfo
*dispatch
;
10228 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10232 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10233 ITypeLib_Release(stdole
);
10237 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10238 ITypeInfo_Release(dispatch
);
10243 old_flags
= This
->wTypeFlags
;
10244 This
->wTypeFlags
= typeFlags
;
10246 hres
= ICreateTypeInfo2_LayOut(iface
);
10247 if (FAILED(hres
)) {
10248 This
->wTypeFlags
= old_flags
;
10255 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10258 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10260 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10263 return E_INVALIDARG
;
10265 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10270 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10273 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10275 TRACE("%p %d\n", This
, helpContext
);
10277 This
->dwHelpContext
= helpContext
;
10282 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10283 WORD majorVerNum
, WORD minorVerNum
)
10285 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10287 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10289 This
->wMajorVerNum
= majorVerNum
;
10290 This
->wMinorVerNum
= minorVerNum
;
10295 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10296 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10298 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10300 ITypeLib
*container
;
10301 TLBRefType
*ref_type
;
10303 TYPEATTR
*typeattr
;
10307 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10309 if (!typeInfo
|| !refType
)
10310 return E_INVALIDARG
;
10312 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10316 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10317 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10319 ITypeLib_Release(container
);
10321 *refType
= target
->hreftype
;
10326 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10327 if (FAILED(hres
)) {
10328 ITypeLib_Release(container
);
10332 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10333 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10334 implib
->lcid
== libattr
->lcid
&&
10335 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10336 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10340 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10341 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10343 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10344 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10345 implib
->name
= SysAllocString(our_container
->path
);
10347 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10348 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10350 implib
->name
= NULL
;
10351 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10355 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10356 implib
->lcid
= libattr
->lcid
;
10357 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10358 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10360 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10363 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10364 ITypeLib_Release(container
);
10366 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10371 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10372 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10373 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10374 ref_type
->tkind
== typeattr
->typekind
)
10379 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10380 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10382 ref_type
->tkind
= typeattr
->typekind
;
10383 ref_type
->pImpTLInfo
= implib
;
10384 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10386 ref_type
->index
= TLB_REF_USE_GUID
;
10388 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10390 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10393 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10395 *refType
= ref_type
->reference
| 0x1;
10397 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10398 This
->pTypeLib
->dispatch_href
= *refType
;
10403 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10404 UINT index
, FUNCDESC
*funcDesc
)
10406 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10407 TLBFuncDesc tmp_func_desc
, *func_desc
;
10412 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10414 if (!funcDesc
|| funcDesc
->oVft
& 3)
10415 return E_INVALIDARG
;
10417 switch (This
->typekind
) {
10419 if (funcDesc
->funckind
!= FUNC_STATIC
)
10420 return TYPE_E_BADMODULEKIND
;
10422 case TKIND_DISPATCH
:
10423 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10424 return TYPE_E_BADMODULEKIND
;
10427 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10428 return TYPE_E_BADMODULEKIND
;
10431 if (index
> This
->cFuncs
)
10432 return TYPE_E_ELEMENTNOTFOUND
;
10434 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10435 !funcDesc
->cParams
)
10436 return TYPE_E_INCONSISTENTPROPFUNCS
;
10439 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10440 funcDesc
->oVft
% 8 != 0)
10441 return E_INVALIDARG
;
10444 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10445 TLBFuncDesc_Constructor(&tmp_func_desc
);
10447 tmp_func_desc
.funcdesc
= *funcDesc
;
10449 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10450 tmp_func_desc
.funcdesc
.oVft
|= 1;
10452 if (funcDesc
->cScodes
) {
10453 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10454 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10456 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10458 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10459 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10460 buf_size
+= sizeof(ELEMDESC
);
10461 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10463 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10464 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10466 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10467 if (FAILED(hres
)) {
10468 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10469 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10473 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10474 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10475 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10476 if (FAILED(hres
)) {
10477 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10478 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10481 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10482 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10483 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10484 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10485 if (FAILED(hres
)) {
10486 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10487 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10493 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10495 if (This
->funcdescs
) {
10496 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10497 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10499 if (index
< This
->cFuncs
) {
10500 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10501 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10502 func_desc
= This
->funcdescs
+ index
;
10504 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10506 /* move custdata lists to the new memory location */
10507 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10509 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10510 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10511 list_init(&fd
->custdata_list
);
10513 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10514 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10519 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10521 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10522 list_init(&func_desc
->custdata_list
);
10526 This
->needs_layout
= TRUE
;
10531 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10532 UINT index
, HREFTYPE refType
)
10534 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10535 TLBImplType
*impl_type
;
10538 TRACE("%p %u %d\n", This
, index
, refType
);
10540 switch(This
->typekind
){
10541 case TKIND_COCLASS
: {
10543 FIXME("Unhandled index: -1\n");
10547 if(index
!= This
->cImplTypes
)
10548 return TYPE_E_ELEMENTNOTFOUND
;
10552 case TKIND_INTERFACE
:
10553 case TKIND_DISPATCH
:
10554 if (index
!= 0 || This
->cImplTypes
)
10555 return TYPE_E_ELEMENTNOTFOUND
;
10558 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10562 if (This
->impltypes
){
10565 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10566 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10568 if (index
< This
->cImplTypes
) {
10569 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10570 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10571 impl_type
= This
->impltypes
+ index
;
10573 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10575 /* move custdata lists to the new memory location */
10576 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10578 TLBImplType
*it
= &This
->impltypes
[i
];
10579 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10580 list_init(&it
->custdata_list
);
10582 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10583 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10588 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10590 memset(impl_type
, 0, sizeof(TLBImplType
));
10591 TLBImplType_Constructor(impl_type
);
10592 impl_type
->hRef
= refType
;
10594 ++This
->cImplTypes
;
10596 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10597 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10599 hres
= ICreateTypeInfo2_LayOut(iface
);
10606 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10607 UINT index
, INT implTypeFlags
)
10609 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10610 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10612 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10614 if (This
->typekind
!= TKIND_COCLASS
)
10615 return TYPE_E_BADMODULEKIND
;
10617 if (index
>= This
->cImplTypes
)
10618 return TYPE_E_ELEMENTNOTFOUND
;
10620 impl_type
->implflags
= implTypeFlags
;
10625 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10628 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10630 TRACE("%p %d\n", This
, alignment
);
10632 This
->cbAlignment
= alignment
;
10637 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10640 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10642 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10645 return E_INVALIDARG
;
10647 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10649 This
->lpstrSchema
= This
->Schema
->str
;
10654 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10655 UINT index
, VARDESC
*varDesc
)
10657 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10658 TLBVarDesc
*var_desc
;
10660 TRACE("%p %u %p\n", This
, index
, varDesc
);
10662 if (This
->vardescs
){
10665 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10666 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10668 if (index
< This
->cVars
) {
10669 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10670 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10671 var_desc
= This
->vardescs
+ index
;
10673 var_desc
= This
->vardescs
+ This
->cVars
;
10675 /* move custdata lists to the new memory location */
10676 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10678 TLBVarDesc
*var
= &This
->vardescs
[i
];
10679 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10680 list_init(&var
->custdata_list
);
10682 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10683 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10688 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10690 TLBVarDesc_Constructor(var_desc
);
10691 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10692 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10696 This
->needs_layout
= TRUE
;
10701 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10702 UINT index
, LPOLESTR
*names
, UINT numNames
)
10704 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10705 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10708 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10711 return E_INVALIDARG
;
10713 if (index
>= This
->cFuncs
|| numNames
== 0)
10714 return TYPE_E_ELEMENTNOTFOUND
;
10716 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10717 if(numNames
> func_desc
->funcdesc
.cParams
)
10718 return TYPE_E_ELEMENTNOTFOUND
;
10720 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10721 return TYPE_E_ELEMENTNOTFOUND
;
10723 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10724 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10725 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10726 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10727 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10728 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10730 return TYPE_E_AMBIGUOUSNAME
;
10734 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10736 for (i
= 1; i
< numNames
; ++i
) {
10737 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10738 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10744 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10745 UINT index
, LPOLESTR name
)
10747 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10749 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10752 return E_INVALIDARG
;
10754 if(index
>= This
->cVars
)
10755 return TYPE_E_ELEMENTNOTFOUND
;
10757 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10761 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10762 TYPEDESC
*tdescAlias
)
10764 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10767 TRACE("%p %p\n", This
, tdescAlias
);
10770 return E_INVALIDARG
;
10772 if(This
->typekind
!= TKIND_ALIAS
)
10773 return TYPE_E_BADMODULEKIND
;
10775 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->cbSizeInstance
, &This
->cbAlignment
);
10779 heap_free(This
->tdescAlias
);
10780 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10781 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10786 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10787 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10789 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10790 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10794 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10795 UINT index
, LPOLESTR docString
)
10797 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10798 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10800 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10803 return E_INVALIDARG
;
10805 if(index
>= This
->cFuncs
)
10806 return TYPE_E_ELEMENTNOTFOUND
;
10808 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10813 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10814 UINT index
, LPOLESTR docString
)
10816 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10817 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10819 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10822 return E_INVALIDARG
;
10824 if(index
>= This
->cVars
)
10825 return TYPE_E_ELEMENTNOTFOUND
;
10827 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10832 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10833 UINT index
, DWORD helpContext
)
10835 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10836 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10838 TRACE("%p %u %d\n", This
, index
, helpContext
);
10840 if(index
>= This
->cFuncs
)
10841 return TYPE_E_ELEMENTNOTFOUND
;
10843 func_desc
->helpcontext
= helpContext
;
10848 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10849 UINT index
, DWORD helpContext
)
10851 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10852 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10854 TRACE("%p %u %d\n", This
, index
, helpContext
);
10856 if(index
>= This
->cVars
)
10857 return TYPE_E_ELEMENTNOTFOUND
;
10859 var_desc
->HelpContext
= helpContext
;
10864 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10865 UINT index
, BSTR bstrMops
)
10867 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10868 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10872 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10875 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10877 TRACE("%p %p\n", This
, idlDesc
);
10880 return E_INVALIDARG
;
10882 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10883 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10888 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10890 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10892 TLBFuncDesc
*func_desc
;
10893 UINT user_vft
= 0, i
, depth
= 0;
10894 HRESULT hres
= S_OK
;
10896 TRACE("%p\n", This
);
10898 This
->needs_layout
= FALSE
;
10900 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10904 if (This
->typekind
== TKIND_INTERFACE
) {
10909 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10911 if (SUCCEEDED(hres
)) {
10912 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10914 if (SUCCEEDED(hres
)) {
10915 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10916 if (FAILED(hres
)) {
10917 ITypeInfo_Release(inh
);
10918 ITypeInfo_Release(tinfo
);
10921 This
->cbSizeVft
= attr
->cbSizeVft
;
10922 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10926 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10927 if(SUCCEEDED(hres
)){
10929 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10930 if(SUCCEEDED(hres
)){
10931 ITypeInfo_Release(inh
);
10935 }while(SUCCEEDED(hres
));
10938 ITypeInfo_Release(inh
);
10939 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10940 This
->cbSizeVft
= 0;
10943 ITypeInfo_Release(tinfo
);
10946 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10947 This
->cbSizeVft
= 0;
10950 ITypeInfo_Release(tinfo
);
10953 } else if (This
->typekind
== TKIND_DISPATCH
)
10954 This
->cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10956 This
->cbSizeVft
= 0;
10958 func_desc
= This
->funcdescs
;
10960 while (i
< This
->cFuncs
) {
10961 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10962 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
10964 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10965 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10967 This
->cbSizeVft
+= This
->pTypeLib
->ptr_size
;
10969 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10972 BOOL reset
= FALSE
;
10974 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10976 iter
= This
->funcdescs
;
10977 while (j
< This
->cFuncs
) {
10978 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10980 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
10983 ++func_desc
->funcdesc
.memid
;
10984 iter
= This
->funcdescs
;
10997 if (user_vft
> This
->cbSizeVft
)
10998 This
->cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11000 for(i
= 0; i
< This
->cVars
; ++i
){
11001 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11002 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11004 BOOL reset
= FALSE
;
11007 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11009 iter
= This
->vardescs
;
11010 while (j
< This
->cVars
) {
11011 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11013 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->cVars
;
11016 ++var_desc
->vardesc
.memid
;
11017 iter
= This
->vardescs
;
11027 ITypeInfo_Release(tinfo
);
11031 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11034 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11035 FIXME("%p %u - stub\n", This
, index
);
11039 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11040 MEMBERID memid
, INVOKEKIND invKind
)
11042 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11043 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11047 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11050 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11051 FIXME("%p %u - stub\n", This
, index
);
11055 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11058 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11059 FIXME("%p %x - stub\n", This
, memid
);
11063 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11066 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11067 FIXME("%p %u - stub\n", This
, index
);
11071 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11072 REFGUID guid
, VARIANT
*varVal
)
11076 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11078 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11080 if (!guid
|| !varVal
)
11081 return E_INVALIDARG
;
11083 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11085 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11088 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11089 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11091 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11092 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11096 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11097 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11099 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11100 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11104 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11105 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11107 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11108 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11112 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11113 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11115 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11116 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11120 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11121 ULONG helpStringContext
)
11123 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11125 TRACE("%p %u\n", This
, helpStringContext
);
11127 This
->dwHelpStringContext
= helpStringContext
;
11132 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11133 UINT index
, ULONG helpStringContext
)
11135 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11136 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11140 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11141 UINT index
, ULONG helpStringContext
)
11143 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11144 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11148 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11150 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11151 FIXME("%p - stub\n", This
);
11155 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11158 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11160 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11163 return E_INVALIDARG
;
11165 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11170 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11171 ICreateTypeInfo2_fnQueryInterface
,
11172 ICreateTypeInfo2_fnAddRef
,
11173 ICreateTypeInfo2_fnRelease
,
11174 ICreateTypeInfo2_fnSetGuid
,
11175 ICreateTypeInfo2_fnSetTypeFlags
,
11176 ICreateTypeInfo2_fnSetDocString
,
11177 ICreateTypeInfo2_fnSetHelpContext
,
11178 ICreateTypeInfo2_fnSetVersion
,
11179 ICreateTypeInfo2_fnAddRefTypeInfo
,
11180 ICreateTypeInfo2_fnAddFuncDesc
,
11181 ICreateTypeInfo2_fnAddImplType
,
11182 ICreateTypeInfo2_fnSetImplTypeFlags
,
11183 ICreateTypeInfo2_fnSetAlignment
,
11184 ICreateTypeInfo2_fnSetSchema
,
11185 ICreateTypeInfo2_fnAddVarDesc
,
11186 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11187 ICreateTypeInfo2_fnSetVarName
,
11188 ICreateTypeInfo2_fnSetTypeDescAlias
,
11189 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11190 ICreateTypeInfo2_fnSetFuncDocString
,
11191 ICreateTypeInfo2_fnSetVarDocString
,
11192 ICreateTypeInfo2_fnSetFuncHelpContext
,
11193 ICreateTypeInfo2_fnSetVarHelpContext
,
11194 ICreateTypeInfo2_fnSetMops
,
11195 ICreateTypeInfo2_fnSetTypeIdldesc
,
11196 ICreateTypeInfo2_fnLayOut
,
11197 ICreateTypeInfo2_fnDeleteFuncDesc
,
11198 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11199 ICreateTypeInfo2_fnDeleteVarDesc
,
11200 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11201 ICreateTypeInfo2_fnDeleteImplType
,
11202 ICreateTypeInfo2_fnSetCustData
,
11203 ICreateTypeInfo2_fnSetFuncCustData
,
11204 ICreateTypeInfo2_fnSetParamCustData
,
11205 ICreateTypeInfo2_fnSetVarCustData
,
11206 ICreateTypeInfo2_fnSetImplTypeCustData
,
11207 ICreateTypeInfo2_fnSetHelpStringContext
,
11208 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11209 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11210 ICreateTypeInfo2_fnInvalidate
,
11211 ICreateTypeInfo2_fnSetName
11214 /******************************************************************************
11215 * ClearCustData (OLEAUT32.171)
11217 * Clear a custom data type's data.
11220 * lpCust [I] The custom data type instance
11225 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11227 if (lpCust
&& lpCust
->cCustData
)
11229 if (lpCust
->prgCustData
)
11233 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11234 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11236 CoTaskMemFree(lpCust
->prgCustData
);
11237 lpCust
->prgCustData
= NULL
;
11239 lpCust
->cCustData
= 0;