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 ((wMaj
!= 0xffff || wMin
!= 0xffff) && (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
);
539 if ((wVerMajor
!=0xffff || wVerMinor
!=0xffff) && *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 TYPEDESC
*tdescAlias
;
1239 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1240 int index
; /* index in this typelib; */
1241 HREFTYPE hreftype
; /* hreftype for app object binding */
1242 /* type libs seem to store the doc strings in ascii
1243 * so why should we do it in unicode?
1245 const TLBString
*Name
;
1246 const TLBString
*DocString
;
1247 const TLBString
*DllName
;
1248 const TLBString
*Schema
;
1249 DWORD dwHelpContext
;
1250 DWORD dwHelpStringContext
;
1253 TLBFuncDesc
*funcdescs
;
1256 TLBVarDesc
*vardescs
;
1258 /* Implemented Interfaces */
1259 TLBImplType
*impltypes
;
1261 struct list
*pcustdata_list
;
1262 struct list custdata_list
;
1265 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1267 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1270 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1272 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1275 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1277 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1280 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1282 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1285 static const ITypeInfo2Vtbl tinfvt
;
1286 static const ITypeCompVtbl tcompvt
;
1287 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1289 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1290 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1292 typedef struct tagTLBContext
1294 unsigned int oStart
; /* start of TLB in file */
1295 unsigned int pos
; /* current pos */
1296 unsigned int length
; /* total length */
1297 void *mapping
; /* memory mapping */
1298 MSFT_SegDir
* pTblDir
;
1299 ITypeLibImpl
* pLibInfo
;
1303 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1305 return str
!= NULL
? str
->str
: NULL
;
1308 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1312 return memcmp(left
, str
->str
, len
);
1315 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1317 return guid
!= NULL
? &guid
->guid
: NULL
;
1320 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1322 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1325 static int get_ptr_size(SYSKIND syskind
)
1335 WARN("Unhandled syskind: 0x%x\n", syskind
);
1342 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1343 if (pTD
->vt
& VT_RESERVED
)
1344 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1345 if (pTD
->vt
& VT_BYREF
)
1346 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1347 if (pTD
->vt
& VT_ARRAY
)
1348 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1349 if (pTD
->vt
& VT_VECTOR
)
1350 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1351 switch(pTD
->vt
& VT_TYPEMASK
) {
1352 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1353 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1354 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1355 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1356 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1357 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1358 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1359 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1360 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1361 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1362 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1363 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1364 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1365 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1366 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1367 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1368 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1369 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1370 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1371 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1372 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1373 pTD
->u
.hreftype
); break;
1374 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1375 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1376 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1377 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1379 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1380 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1382 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1383 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1384 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1387 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1391 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1393 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1394 dump_TypeDesc(&edesc
->tdesc
,buf
);
1395 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1396 MESSAGE("\t\tu.paramdesc.wParamFlags");
1397 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1398 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1399 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1400 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1401 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1402 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1403 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1404 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1405 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1407 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1409 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1410 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1411 MESSAGE("Param %d:\n",i
);
1412 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1414 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1415 switch (funcdesc
->funckind
) {
1416 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1417 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1418 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1419 case FUNC_STATIC
: MESSAGE("static");break;
1420 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1421 default: MESSAGE("unknown");break;
1423 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1424 switch (funcdesc
->invkind
) {
1425 case INVOKE_FUNC
: MESSAGE("func");break;
1426 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1427 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1428 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1430 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1431 switch (funcdesc
->callconv
) {
1432 case CC_CDECL
: MESSAGE("cdecl");break;
1433 case CC_PASCAL
: MESSAGE("pascal");break;
1434 case CC_STDCALL
: MESSAGE("stdcall");break;
1435 case CC_SYSCALL
: MESSAGE("syscall");break;
1438 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1439 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1440 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1442 MESSAGE("\telemdescFunc (return value type):\n");
1443 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1446 static const char * const typekind_desc
[] =
1459 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1462 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1463 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1464 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1467 dump_FUNCDESC(&(pfd
->funcdesc
));
1469 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1470 if(pfd
->Entry
== NULL
)
1471 MESSAGE("\tentry: (null)\n");
1472 else if(pfd
->Entry
== (void*)-1)
1473 MESSAGE("\tentry: invalid\n");
1474 else if(IS_INTRESOURCE(pfd
->Entry
))
1475 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1477 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1479 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1483 dump_TLBFuncDescOne(pfd
);
1488 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1492 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1498 static void dump_TLBImpLib(const TLBImpLib
*import
)
1500 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1501 debugstr_w(import
->name
));
1502 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1503 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1506 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1510 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1512 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1513 if(ref
->index
== -1)
1514 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1516 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1518 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1520 TRACE_(typelib
)("in lib\n");
1521 dump_TLBImpLib(ref
->pImpTLInfo
);
1526 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1531 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1532 impl
->hRef
, impl
->implflags
);
1538 static void dump_DispParms(const DISPPARAMS
* pdp
)
1542 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1544 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1546 TRACE("named args:\n");
1547 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1548 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1551 if (pdp
->cArgs
&& pdp
->rgvarg
)
1554 for (index
= 0; index
< pdp
->cArgs
; index
++)
1555 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1559 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1561 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1562 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1563 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1564 TRACE("kind:%s\n", typekind_desc
[pty
->typeattr
.typekind
]);
1565 TRACE("fct:%u var:%u impl:%u\n", pty
->typeattr
.cFuncs
, pty
->typeattr
.cVars
, pty
->typeattr
.cImplTypes
);
1566 TRACE("wTypeFlags: 0x%04x\n", pty
->typeattr
.wTypeFlags
);
1567 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1568 if (pty
->typeattr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1570 dump_TLBFuncDesc(pty
->funcdescs
, pty
->typeattr
.cFuncs
);
1571 dump_TLBVarDesc(pty
->vardescs
, pty
->typeattr
.cVars
);
1572 dump_TLBImplType(pty
->impltypes
, pty
->typeattr
.cImplTypes
);
1575 static void dump_VARDESC(const VARDESC
*v
)
1577 MESSAGE("memid %d\n",v
->memid
);
1578 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1579 MESSAGE("oInst %d\n",v
->u
.oInst
);
1580 dump_ELEMDESC(&(v
->elemdescVar
));
1581 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1582 MESSAGE("varkind %d\n",v
->varkind
);
1585 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1587 /* VT_LPWSTR is largest type that, may appear in type description */
1588 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1589 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1590 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1591 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1592 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1593 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1594 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1595 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1598 static void TLB_abort(void)
1603 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1605 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1606 if (!ret
) ERR("cannot allocate memory\n");
1610 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1612 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1613 if (!ret
) ERR("cannot allocate memory\n");
1617 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1619 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1622 void heap_free(void *ptr
)
1624 HeapFree(GetProcessHeap(), 0, ptr
);
1627 /* returns the size required for a deep copy of a typedesc into a
1629 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1633 if (alloc_initial_space
)
1634 size
+= sizeof(TYPEDESC
);
1640 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1643 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1644 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1650 /* deep copy a typedesc into a flat buffer */
1651 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1656 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1665 dest
->u
.lptdesc
= buffer
;
1666 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1669 dest
->u
.lpadesc
= buffer
;
1670 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1671 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1672 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1678 /* free custom data allocated by MSFT_CustData */
1679 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1681 TLBCustData
*cd
, *cdn
;
1682 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1684 list_remove(&cd
->entry
);
1685 VariantClear(&cd
->data
);
1690 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1695 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1696 ret
= SysAllocStringLen(NULL
, len
- 1);
1697 if (!ret
) return ret
;
1698 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1702 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1703 UINT n
, MEMBERID memid
)
1706 if(funcdescs
->funcdesc
.memid
== memid
)
1714 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1715 UINT n
, MEMBERID memid
)
1718 if(vardescs
->vardesc
.memid
== memid
)
1726 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1727 UINT n
, const OLECHAR
*name
)
1730 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1738 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1740 TLBCustData
*cust_data
;
1741 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1742 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1747 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1748 UINT n
, const OLECHAR
*name
)
1751 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1759 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1761 list_init(&var_desc
->custdata_list
);
1764 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1768 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1773 TLBVarDesc_Constructor(&ret
[n
-1]);
1780 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1784 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1789 list_init(&ret
[n
-1].custdata_list
);
1796 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1798 list_init(&func_desc
->custdata_list
);
1801 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1805 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1810 TLBFuncDesc_Constructor(&ret
[n
-1]);
1817 static void TLBImplType_Constructor(TLBImplType
*impl
)
1819 list_init(&impl
->custdata_list
);
1822 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1826 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1831 TLBImplType_Constructor(&ret
[n
-1]);
1838 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1839 const GUID
*new_guid
, HREFTYPE hreftype
)
1843 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1844 if (IsEqualGUID(&guid
->guid
, new_guid
))
1848 guid
= heap_alloc(sizeof(TLBGuid
));
1852 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1853 guid
->hreftype
= hreftype
;
1855 list_add_tail(guid_list
, &guid
->entry
);
1860 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1862 TLBCustData
*cust_data
;
1874 return DISP_E_BADVARTYPE
;
1877 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1880 cust_data
= heap_alloc(sizeof(TLBCustData
));
1882 return E_OUTOFMEMORY
;
1884 cust_data
->guid
= tlbguid
;
1885 VariantInit(&cust_data
->data
);
1887 list_add_tail(custdata_list
, &cust_data
->entry
);
1889 VariantClear(&cust_data
->data
);
1891 return VariantCopy(&cust_data
->data
, var
);
1894 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1901 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1902 if (strcmpW(str
->str
, new_str
) == 0)
1906 str
= heap_alloc(sizeof(TLBString
));
1910 str
->str
= SysAllocString(new_str
);
1916 list_add_tail(string_list
, &str
->entry
);
1921 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1922 ULONG
*size
, WORD
*align
)
1928 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1932 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1934 ITypeInfo_Release(other
);
1939 *size
= attr
->cbSizeInstance
;
1941 *align
= attr
->cbAlignment
;
1943 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1944 ITypeInfo_Release(other
);
1949 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1950 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1952 ULONG i
, sub
, ptr_size
;
1955 ptr_size
= get_ptr_size(sys
);
1994 *size
= sizeof(DATE
);
1997 *size
= sizeof(VARIANT
);
1999 if(sys
== SYS_WIN32
)
2000 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2004 *size
= sizeof(DECIMAL
);
2011 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2012 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2013 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2018 case VT_USERDEFINED
:
2019 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2021 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2035 /**********************************************************************
2037 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2040 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2042 if (where
!= DO_NOT_SEEK
)
2044 where
+= pcx
->oStart
;
2045 if (where
> pcx
->length
)
2048 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2056 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2058 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2059 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2061 MSFT_Seek(pcx
, where
);
2062 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2063 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2068 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2073 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2074 FromLEDWords(buffer
, ret
);
2079 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2084 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2085 FromLEWords(buffer
, ret
);
2090 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2093 MSFT_GuidEntry entry
;
2096 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2098 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2101 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2103 guid
= heap_alloc(sizeof(TLBGuid
));
2105 guid
->offset
= offs
;
2106 guid
->guid
= entry
.guid
;
2107 guid
->hreftype
= entry
.hreftype
;
2109 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2111 offs
+= sizeof(MSFT_GuidEntry
);
2115 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2119 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2120 if(ret
->offset
== offset
){
2121 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2129 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2131 MSFT_NameIntro niName
;
2135 ERR_(typelib
)("bad offset %d\n", offset
);
2139 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2140 pcx
->pTblDir
->pNametab
.offset
+offset
);
2142 return niName
.hreftype
;
2145 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2148 MSFT_NameIntro intro
;
2150 int offs
= 0, lengthInChars
;
2152 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2156 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2159 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2160 intro
.namelen
&= 0xFF;
2161 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2163 len_piece
= (len_piece
+ 4) & ~0x3;
2167 string
= heap_alloc(len_piece
+ 1);
2168 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2169 string
[intro
.namelen
] = '\0';
2171 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2172 string
, -1, NULL
, 0);
2173 if (!lengthInChars
) {
2175 return E_UNEXPECTED
;
2178 tlbstr
= heap_alloc(sizeof(TLBString
));
2180 tlbstr
->offset
= offs
;
2181 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2182 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2186 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2192 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2196 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2197 if (tlbstr
->offset
== offset
) {
2198 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2206 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2210 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2211 if (tlbstr
->offset
== offset
) {
2212 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2221 * read a value and fill a VARIANT structure
2223 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2227 TRACE_(typelib
)("\n");
2229 if(offset
<0) { /* data are packed in here */
2230 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2231 V_I4(pVar
) = offset
& 0x3ffffff;
2234 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2235 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2236 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2237 switch (V_VT(pVar
)){
2238 case VT_EMPTY
: /* FIXME: is this right? */
2239 case VT_NULL
: /* FIXME: is this right? */
2240 case VT_I2
: /* this should not happen */
2251 case VT_VOID
: /* FIXME: is this right? */
2259 case VT_DECIMAL
: /* FIXME: is this right? */
2262 /* pointer types with known behaviour */
2265 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2267 V_BSTR(pVar
) = NULL
;
2269 ptr
= heap_alloc_zero(size
);
2270 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2271 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2272 /* FIXME: do we need a AtoW conversion here? */
2273 V_UNION(pVar
, bstrVal
[size
])='\0';
2274 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2279 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2286 case VT_USERDEFINED
:
2292 case VT_STREAMED_OBJECT
:
2293 case VT_STORED_OBJECT
:
2294 case VT_BLOB_OBJECT
:
2299 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2303 if(size
>0) /* (big|small) endian correct? */
2304 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2308 * create a linked list with custom data
2310 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2316 TRACE_(typelib
)("\n");
2318 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2322 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2323 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2324 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2325 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2326 list_add_head(custdata_list
, &pNew
->entry
);
2327 offset
= entry
.next
;
2332 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2335 pTd
->vt
=type
& VT_TYPEMASK
;
2337 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2339 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2342 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2344 return (invkind
== INVOKE_PROPERTYGET
||
2345 invkind
== INVOKE_PROPERTYPUT
||
2346 invkind
== INVOKE_PROPERTYPUTREF
);
2350 MSFT_DoFuncs(TLBContext
* pcx
,
2355 TLBFuncDesc
** pptfd
)
2358 * member information is stored in a data structure at offset
2359 * indicated by the memoffset field of the typeinfo structure
2360 * There are several distinctive parts.
2361 * The first part starts with a field that holds the total length
2362 * of this (first) part excluding this field. Then follow the records,
2363 * for each member there is one record.
2365 * The first entry is always the length of the record (including this
2367 * The rest of the record depends on the type of the member. If there is
2368 * a field indicating the member type (function, variable, interface, etc)
2369 * I have not found it yet. At this time we depend on the information
2370 * in the type info and the usual order how things are stored.
2372 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2375 * Third is an equal sized array with file offsets to the name entry
2378 * The fourth and last (?) part is an array with offsets to the records
2379 * in the first part of this file segment.
2382 int infolen
, nameoffset
, reclength
, i
;
2383 int recoffset
= offset
+ sizeof(INT
);
2385 char *recbuf
= heap_alloc(0xffff);
2386 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2387 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2389 TRACE_(typelib
)("\n");
2391 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2393 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2395 for ( i
= 0; i
< cFuncs
; i
++ )
2399 /* name, eventually add to a hash table */
2400 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2401 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2403 /* read the function information record */
2404 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2406 reclength
&= 0xffff;
2408 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2410 /* size without argument data */
2411 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2412 if (pFuncRec
->FKCCIC
& 0x1000)
2413 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2415 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2416 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2418 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2419 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2421 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2423 if (pFuncRec
->FKCCIC
& 0x2000 )
2425 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2426 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2427 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2430 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2433 ptfd
->Entry
= (TLBString
*)-1;
2435 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2436 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2438 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2439 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2441 /* fill the FuncDesc Structure */
2442 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2443 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2445 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2446 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2447 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2448 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2449 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2450 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2451 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2453 /* nameoffset is sometimes -1 on the second half of a propget/propput
2454 * pair of functions */
2455 if ((nameoffset
== -1) && (i
> 0) &&
2456 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2457 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2458 ptfd
->Name
= ptfd_prev
->Name
;
2460 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2464 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2466 /* do the parameters/arguments */
2467 if(pFuncRec
->nrargs
)
2470 MSFT_ParameterInfo paraminfo
;
2472 ptfd
->funcdesc
.lprgelemdescParam
=
2473 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2475 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2477 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2478 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2480 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2482 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2488 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2491 if (paraminfo
.oName
!= -1)
2492 ptfd
->pParamDesc
[j
].Name
=
2493 MSFT_ReadName( pcx
, paraminfo
.oName
);
2494 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2497 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2498 (pFuncRec
->FKCCIC
& 0x1000) )
2500 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2502 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2504 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2506 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2507 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2509 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2513 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2516 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2517 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2518 pFuncRec
->FKCCIC
& 0x80 )
2521 pFuncRec
->oArgCustData
[j
],
2522 &ptfd
->pParamDesc
[j
].custdata_list
);
2525 /* SEEK value = jump to offset,
2526 * from there jump to the end of record,
2527 * go back by (j-1) arguments
2529 MSFT_ReadLEDWords( ¶minfo
,
2530 sizeof(MSFT_ParameterInfo
), pcx
,
2531 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2532 * sizeof(MSFT_ParameterInfo
)));
2536 /* scode is not used: archaic win16 stuff FIXME: right? */
2537 ptfd
->funcdesc
.cScodes
= 0 ;
2538 ptfd
->funcdesc
.lprgscode
= NULL
;
2542 recoffset
+= reclength
;
2547 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2548 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2550 int infolen
, nameoffset
, reclength
;
2552 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2557 TRACE_(typelib
)("\n");
2559 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2560 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2561 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2562 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2563 recoffset
+= offset
+sizeof(INT
);
2564 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2565 /* name, eventually add to a hash table */
2566 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2567 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2568 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2569 /* read the variable information record */
2570 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2572 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2575 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2576 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2578 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2579 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2581 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2582 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2584 /* fill the VarDesc Structure */
2585 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2586 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2587 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2588 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2589 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2590 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2591 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2592 if(pVarRec
->VarKind
== VAR_CONST
){
2593 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2594 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2595 pVarRec
->OffsValue
, pcx
);
2597 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2598 recoffset
+= reclength
;
2602 /* process Implemented Interfaces of a com class */
2603 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2607 MSFT_RefRecord refrec
;
2610 TRACE_(typelib
)("\n");
2612 pTI
->impltypes
= TLBImplType_Alloc(count
);
2613 pImpl
= pTI
->impltypes
;
2614 for(i
=0;i
<count
;i
++){
2615 if(offset
<0) break; /* paranoia */
2616 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2617 pImpl
->hRef
= refrec
.reftype
;
2618 pImpl
->implflags
=refrec
.flags
;
2619 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2620 offset
=refrec
.onext
;
2626 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2627 * and some structures, and fix the alignment */
2628 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2630 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2631 switch(info
->tdescAlias
->vt
){
2639 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2640 info
->typeattr
.cbAlignment
= sizeof(void*);
2643 case VT_USERDEFINED
:
2644 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2647 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2648 info
->typeattr
.cbAlignment
= 8;
2650 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2651 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2653 info
->typeattr
.cbAlignment
= sizeof(void*);
2656 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2657 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2658 info
->typeattr
.typekind
== TKIND_COCLASS
){
2659 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2660 info
->typeattr
.cbAlignment
= sizeof(void*);
2666 * process a typeinfo record
2668 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2671 ITypeLibImpl
* pLibInfo
)
2673 MSFT_TypeInfoBase tiBase
;
2674 ITypeInfoImpl
*ptiRet
;
2676 TRACE_(typelib
)("count=%u\n", count
);
2678 ptiRet
= ITypeInfoImpl_Constructor();
2679 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2680 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2682 /* this is where we are coming from */
2683 ptiRet
->pTypeLib
= pLibInfo
;
2684 ptiRet
->index
=count
;
2686 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2687 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2688 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2689 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2690 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2691 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2692 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2693 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2694 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2695 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2696 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2697 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2698 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2699 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2701 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2702 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2703 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2707 /* IDLDESC idldescType; *//* never saw this one != zero */
2709 /* name, eventually add to a hash table */
2710 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2711 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2712 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2714 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2715 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2716 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2718 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2719 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2721 /* note: InfoType's Help file and HelpStringDll come from the containing
2722 * library. Further HelpString and Docstring appear to be the same thing :(
2725 if(ptiRet
->typeattr
.cFuncs
>0 )
2726 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2727 ptiRet
->typeattr
.cVars
,
2728 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2730 if(ptiRet
->typeattr
.cVars
>0 )
2731 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2732 ptiRet
->typeattr
.cVars
,
2733 tiBase
.memoffset
, &ptiRet
->vardescs
);
2734 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2735 switch(ptiRet
->typeattr
.typekind
)
2738 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2741 case TKIND_DISPATCH
:
2742 /* This is not -1 when the interface is a non-base dual interface or
2743 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2744 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2748 if (tiBase
.datatype1
!= -1)
2750 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2751 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2755 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2756 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2760 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2762 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2763 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2764 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2765 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2766 if (TRACE_ON(typelib
))
2767 dump_TypeInfo(ptiRet
);
2772 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2775 INT16 len_str
, len_piece
;
2776 int offs
= 0, lengthInChars
;
2778 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2782 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2785 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2786 len_piece
= len_str
+ sizeof(INT16
);
2788 len_piece
= (len_piece
+ 4) & ~0x3;
2792 string
= heap_alloc(len_piece
+ 1);
2793 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2794 string
[len_str
] = '\0';
2796 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2797 string
, -1, NULL
, 0);
2798 if (!lengthInChars
) {
2800 return E_UNEXPECTED
;
2803 tlbstr
= heap_alloc(sizeof(TLBString
));
2805 tlbstr
->offset
= offs
;
2806 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2807 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2811 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2817 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2822 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2823 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2824 MSFT_ImpInfo impinfo
;
2827 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2829 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2830 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2832 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2833 if(pImpLib
->offset
==impinfo
.oImpFile
)
2836 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2837 ref
->reference
= offs
;
2838 ref
->pImpTLInfo
= pImpLib
;
2839 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2840 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2841 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2842 ref
->index
= TLB_REF_USE_GUID
;
2844 ref
->index
= impinfo
.oGuid
;
2846 ERR("Cannot find a reference\n");
2847 ref
->reference
= -1;
2848 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2851 offs
+= sizeof(impinfo
);
2857 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2858 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2859 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2862 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2863 static CRITICAL_SECTION cache_section
;
2864 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2866 0, 0, &cache_section
,
2867 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2868 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2870 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2873 typedef struct TLB_PEFile
2875 IUnknown IUnknown_iface
;
2878 HRSRC typelib_resource
;
2879 HGLOBAL typelib_global
;
2880 LPVOID typelib_base
;
2883 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2885 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2888 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2890 if (IsEqualIID(riid
, &IID_IUnknown
))
2893 IUnknown_AddRef(iface
);
2897 return E_NOINTERFACE
;
2900 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2902 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2903 return InterlockedIncrement(&This
->refs
);
2906 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2908 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2909 ULONG refs
= InterlockedDecrement(&This
->refs
);
2912 if (This
->typelib_global
)
2913 FreeResource(This
->typelib_global
);
2915 FreeLibrary(This
->dll
);
2921 static const IUnknownVtbl TLB_PEFile_Vtable
=
2923 TLB_PEFile_QueryInterface
,
2928 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2931 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2933 This
= heap_alloc(sizeof(TLB_PEFile
));
2935 return E_OUTOFMEMORY
;
2937 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2940 This
->typelib_resource
= NULL
;
2941 This
->typelib_global
= NULL
;
2942 This
->typelib_base
= NULL
;
2944 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2945 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2949 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2950 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2951 if (This
->typelib_resource
)
2953 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2954 if (This
->typelib_global
)
2956 This
->typelib_base
= LockResource(This
->typelib_global
);
2958 if (This
->typelib_base
)
2960 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2961 *ppBase
= This
->typelib_base
;
2962 *ppFile
= &This
->IUnknown_iface
;
2968 TRACE("No TYPELIB resource found\n");
2972 TLB_PEFile_Release(&This
->IUnknown_iface
);
2976 typedef struct TLB_NEFile
2978 IUnknown IUnknown_iface
;
2980 LPVOID typelib_base
;
2983 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2985 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2988 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2990 if (IsEqualIID(riid
, &IID_IUnknown
))
2993 IUnknown_AddRef(iface
);
2997 return E_NOINTERFACE
;
3000 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
3002 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3003 return InterlockedIncrement(&This
->refs
);
3006 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
3008 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3009 ULONG refs
= InterlockedDecrement(&This
->refs
);
3012 heap_free(This
->typelib_base
);
3018 static const IUnknownVtbl TLB_NEFile_Vtable
=
3020 TLB_NEFile_QueryInterface
,
3025 /***********************************************************************
3026 * read_xx_header [internal]
3028 static int read_xx_header( HFILE lzfd
)
3030 IMAGE_DOS_HEADER mzh
;
3033 LZSeek( lzfd
, 0, SEEK_SET
);
3034 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3036 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3039 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3040 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3043 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3045 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3046 return IMAGE_OS2_SIGNATURE
;
3047 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3048 return IMAGE_NT_SIGNATURE
;
3051 WARN("Can't handle %s files.\n", magic
);
3056 /***********************************************************************
3057 * find_ne_resource [internal]
3059 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3060 DWORD
*resLen
, DWORD
*resOff
)
3062 IMAGE_OS2_HEADER nehd
;
3063 NE_TYPEINFO
*typeInfo
;
3064 NE_NAMEINFO
*nameInfo
;
3070 /* Read in NE header */
3071 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3072 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3074 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3077 TRACE("No resources in NE dll\n" );
3081 /* Read in resource table */
3082 resTab
= heap_alloc( resTabSize
);
3083 if ( !resTab
) return FALSE
;
3085 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3086 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3088 heap_free( resTab
);
3093 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3095 if (!IS_INTRESOURCE(typeid)) /* named type */
3097 BYTE len
= strlen( typeid );
3098 while (typeInfo
->type_id
)
3100 if (!(typeInfo
->type_id
& 0x8000))
3102 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3103 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
3105 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3106 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3109 else /* numeric type id */
3111 WORD id
= LOWORD(typeid) | 0x8000;
3112 while (typeInfo
->type_id
)
3114 if (typeInfo
->type_id
== id
) goto found_type
;
3115 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3116 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3119 TRACE("No typeid entry found for %p\n", typeid );
3120 heap_free( resTab
);
3124 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3126 if (!IS_INTRESOURCE(resid
)) /* named resource */
3128 BYTE len
= strlen( resid
);
3129 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3131 BYTE
*p
= resTab
+ nameInfo
->id
;
3132 if (nameInfo
->id
& 0x8000) continue;
3133 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3136 else /* numeric resource id */
3138 WORD id
= LOWORD(resid
) | 0x8000;
3139 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3140 if (nameInfo
->id
== id
) goto found_name
;
3142 TRACE("No resid entry found for %p\n", typeid );
3143 heap_free( resTab
);
3147 /* Return resource data */
3148 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3149 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3151 heap_free( resTab
);
3155 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3159 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3162 This
= heap_alloc(sizeof(TLB_NEFile
));
3163 if (!This
) return E_OUTOFMEMORY
;
3165 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3167 This
->typelib_base
= NULL
;
3169 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3170 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3172 DWORD reslen
, offset
;
3173 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3175 This
->typelib_base
= heap_alloc(reslen
);
3176 if( !This
->typelib_base
)
3180 LZSeek( lzfd
, offset
, SEEK_SET
);
3181 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3183 *ppBase
= This
->typelib_base
;
3184 *pdwTLBLength
= reslen
;
3185 *ppFile
= &This
->IUnknown_iface
;
3191 if( lzfd
>= 0) LZClose( lzfd
);
3192 TLB_NEFile_Release(&This
->IUnknown_iface
);
3196 typedef struct TLB_Mapping
3198 IUnknown IUnknown_iface
;
3202 LPVOID typelib_base
;
3205 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3207 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3210 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3212 if (IsEqualIID(riid
, &IID_IUnknown
))
3215 IUnknown_AddRef(iface
);
3219 return E_NOINTERFACE
;
3222 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3224 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3225 return InterlockedIncrement(&This
->refs
);
3228 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3230 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3231 ULONG refs
= InterlockedDecrement(&This
->refs
);
3234 if (This
->typelib_base
)
3235 UnmapViewOfFile(This
->typelib_base
);
3237 CloseHandle(This
->mapping
);
3238 if (This
->file
!= INVALID_HANDLE_VALUE
)
3239 CloseHandle(This
->file
);
3245 static const IUnknownVtbl TLB_Mapping_Vtable
=
3247 TLB_Mapping_QueryInterface
,
3252 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3256 This
= heap_alloc(sizeof(TLB_Mapping
));
3258 return E_OUTOFMEMORY
;
3260 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3262 This
->file
= INVALID_HANDLE_VALUE
;
3263 This
->mapping
= NULL
;
3264 This
->typelib_base
= NULL
;
3266 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3267 if (INVALID_HANDLE_VALUE
!= This
->file
)
3269 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3272 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3273 if(This
->typelib_base
)
3275 /* retrieve file size */
3276 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3277 *ppBase
= This
->typelib_base
;
3278 *ppFile
= &This
->IUnknown_iface
;
3284 IUnknown_Release(&This
->IUnknown_iface
);
3285 return TYPE_E_CANTLOADLIBRARY
;
3288 /****************************************************************************
3291 * find the type of the typelib file and map the typelib resource into
3295 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3296 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3298 ITypeLibImpl
*entry
;
3301 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3302 LPVOID pBase
= NULL
;
3303 DWORD dwTLBLength
= 0;
3304 IUnknown
*pFile
= NULL
;
3309 index_str
= strrchrW(pszFileName
, '\\');
3310 if(index_str
&& *++index_str
!= '\0')
3313 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3314 if(*end_ptr
== '\0')
3316 int str_len
= index_str
- pszFileName
- 1;
3318 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3319 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3324 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3326 if(strchrW(file
, '\\'))
3328 lstrcpyW(pszPath
, file
);
3332 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3333 pszPath
[len
] = '\\';
3334 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3338 if(file
!= pszFileName
) heap_free(file
);
3340 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3341 if(h
!= INVALID_HANDLE_VALUE
){
3342 FILE_NAME_INFORMATION size_info
;
3345 /* GetFileInformationByHandleEx returns the path of the file without
3346 * WOW64 redirection */
3347 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, &size_info
, sizeof(size_info
));
3348 if(br
|| GetLastError() == ERROR_MORE_DATA
){
3349 FILE_NAME_INFORMATION
*info
;
3350 DWORD size
= sizeof(*info
) + size_info
.FileNameLength
+ sizeof(WCHAR
);
3352 info
= HeapAlloc(GetProcessHeap(), 0, size
);
3354 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, info
, size
);
3356 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3357 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3360 HeapFree(GetProcessHeap(), 0, info
);
3366 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3368 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3369 EnterCriticalSection(&cache_section
);
3370 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3372 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3374 TRACE("cache hit\n");
3375 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3376 ITypeLib2_AddRef(*ppTypeLib
);
3377 LeaveCriticalSection(&cache_section
);
3381 LeaveCriticalSection(&cache_section
);
3383 /* now actually load and parse the typelib */
3385 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3386 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3387 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3388 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3389 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3392 if (dwTLBLength
>= 4)
3394 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3395 if (dwSignature
== MSFT_SIGNATURE
)
3396 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3397 else if (dwSignature
== SLTG_SIGNATURE
)
3398 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3401 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3402 ret
= TYPE_E_CANTLOADLIBRARY
;
3406 ret
= TYPE_E_CANTLOADLIBRARY
;
3407 IUnknown_Release(pFile
);
3411 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3413 TRACE("adding to cache\n");
3414 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3415 lstrcpyW(impl
->path
, pszPath
);
3416 /* We should really canonicalise the path here. */
3417 impl
->index
= index
;
3419 /* FIXME: check if it has added already in the meantime */
3420 EnterCriticalSection(&cache_section
);
3421 list_add_head(&tlb_cache
, &impl
->entry
);
3422 LeaveCriticalSection(&cache_section
);
3428 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3430 ret
= TYPE_E_CANTLOADLIBRARY
;
3437 /*================== ITypeLib(2) Methods ===================================*/
3439 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3441 ITypeLibImpl
* pTypeLibImpl
;
3443 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3444 if (!pTypeLibImpl
) return NULL
;
3446 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3447 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3448 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3449 pTypeLibImpl
->ref
= 1;
3451 list_init(&pTypeLibImpl
->implib_list
);
3452 list_init(&pTypeLibImpl
->custdata_list
);
3453 list_init(&pTypeLibImpl
->name_list
);
3454 list_init(&pTypeLibImpl
->string_list
);
3455 list_init(&pTypeLibImpl
->guid_list
);
3456 list_init(&pTypeLibImpl
->ref_list
);
3457 pTypeLibImpl
->dispatch_href
= -1;
3459 return pTypeLibImpl
;
3462 /****************************************************************************
3463 * ITypeLib2_Constructor_MSFT
3465 * loading an MSFT typelib from an in-memory image
3467 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3471 MSFT_Header tlbHeader
;
3472 MSFT_SegDir tlbSegDir
;
3473 ITypeLibImpl
* pTypeLibImpl
;
3476 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3478 pTypeLibImpl
= TypeLibImpl_Constructor();
3479 if (!pTypeLibImpl
) return NULL
;
3481 /* get pointer to beginning of typelib data */
3485 cx
.pLibInfo
= pTypeLibImpl
;
3486 cx
.length
= dwTLBLength
;
3489 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3490 TRACE_(typelib
)("header:\n");
3491 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3492 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3493 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3496 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3498 /* there is a small amount of information here until the next important
3500 * the segment directory . Try to calculate the amount of data */
3501 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3503 /* now read the segment directory */
3504 TRACE("read segment directory (at %d)\n",lPSegDir
);
3505 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3506 cx
.pTblDir
= &tlbSegDir
;
3508 /* just check two entries */
3509 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3511 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3512 heap_free(pTypeLibImpl
);
3516 MSFT_ReadAllNames(&cx
);
3517 MSFT_ReadAllStrings(&cx
);
3518 MSFT_ReadAllGuids(&cx
);
3520 /* now fill our internal data */
3521 /* TLIBATTR fields */
3522 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3524 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3525 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3526 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3527 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3528 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3530 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3531 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3533 /* name, eventually add to a hash table */
3534 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3537 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3538 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3540 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3543 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3544 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3547 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3550 if(tlbHeader
.CustomDataOffset
>= 0)
3552 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3555 /* fill in type descriptions */
3556 if(tlbSegDir
.pTypdescTab
.length
> 0)
3558 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3560 pTypeLibImpl
->ctTypeDesc
= cTD
;
3561 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3562 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3565 /* FIXME: add several sanity checks here */
3566 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3567 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3569 /* FIXME: check safearray */
3571 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3573 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3575 else if(td
[0] == VT_CARRAY
)
3577 /* array descr table here */
3578 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3580 else if(td
[0] == VT_USERDEFINED
)
3582 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3584 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3587 /* second time around to fill the array subscript info */
3590 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3591 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3593 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3594 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3597 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3599 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3601 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3603 for(j
= 0; j
<td
[2]; j
++)
3605 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3606 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3607 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3608 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3613 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3614 ERR("didn't find array description data\n");
3619 /* imported type libs */
3620 if(tlbSegDir
.pImpFiles
.offset
>0)
3623 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3626 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3630 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3631 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3632 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3634 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3635 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3636 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3637 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3640 name
= heap_alloc_zero(size
+1);
3641 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3642 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3645 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3646 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3648 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3652 MSFT_ReadAllRefs(&cx
);
3654 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3657 if(tlbHeader
.nrtypeinfos
>= 0 )
3659 ITypeInfoImpl
**ppTI
;
3661 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3663 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3665 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3668 (pTypeLibImpl
->TypeInfoCount
)++;
3673 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3674 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3675 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3679 TRACE("(%p)\n", pTypeLibImpl
);
3680 return &pTypeLibImpl
->ITypeLib2_iface
;
3684 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3690 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3691 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3695 guid
->Data4
[0] = s
>> 8;
3696 guid
->Data4
[1] = s
& 0xff;
3699 for(i
= 0; i
< 6; i
++) {
3700 memcpy(b
, str
+ 24 + 2 * i
, 2);
3701 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3706 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3713 bytelen
= *(const WORD
*)ptr
;
3714 if(bytelen
== 0xffff) return 2;
3716 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3717 tmp_str
= SysAllocStringLen(NULL
, len
);
3719 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3720 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3721 SysFreeString(tmp_str
);
3726 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3731 bytelen
= *(const WORD
*)ptr
;
3732 if(bytelen
== 0xffff) return 2;
3733 *str
= heap_alloc(bytelen
+ 1);
3734 memcpy(*str
, ptr
+ 2, bytelen
);
3735 (*str
)[bytelen
] = '\0';
3739 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3744 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3745 if (tlbstr
->offset
== offset
)
3749 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3750 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3751 SysFreeString(tmp_str
);
3756 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3758 char *ptr
= pLibBlk
;
3761 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3762 FIXME("libblk magic = %04x\n", w
);
3767 if((w
= *(WORD
*)ptr
) != 0xffff) {
3768 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3773 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3775 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3777 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3780 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3781 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3784 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3785 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3787 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3790 ptr
+= 4; /* skip res12 */
3792 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3795 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3798 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3801 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3802 ptr
+= sizeof(GUID
);
3804 return ptr
- (char*)pLibBlk
;
3807 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3812 } sltg_ref_lookup_t
;
3814 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3815 HREFTYPE
*typelib_ref
)
3817 if(table
&& typeinfo_ref
< table
->num
)
3819 *typelib_ref
= table
->refs
[typeinfo_ref
];
3823 ERR_(typelib
)("Unable to find reference\n");
3828 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3833 if((*pType
& 0xe00) == 0xe00) {
3835 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3836 pTD
= pTD
->u
.lptdesc
;
3838 switch(*pType
& 0x3f) {
3841 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3842 pTD
= pTD
->u
.lptdesc
;
3845 case VT_USERDEFINED
:
3846 pTD
->vt
= VT_USERDEFINED
;
3847 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3853 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3856 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3858 pTD
->vt
= VT_CARRAY
;
3859 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3860 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3861 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3862 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3864 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3870 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3874 pTD
->vt
= VT_SAFEARRAY
;
3875 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3876 pTD
= pTD
->u
.lptdesc
;
3880 pTD
->vt
= *pType
& 0x3f;
3889 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3890 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3892 /* Handle [in/out] first */
3893 if((*pType
& 0xc000) == 0xc000)
3894 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3895 else if(*pType
& 0x8000)
3896 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3897 else if(*pType
& 0x4000)
3898 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3900 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3903 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3906 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3908 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3912 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3917 TLBRefType
*ref_type
;
3918 sltg_ref_lookup_t
*table
;
3919 HREFTYPE typelib_ref
;
3921 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3922 FIXME("Ref magic = %x\n", pRef
->magic
);
3925 name
= ( (char*)pRef
->names
+ pRef
->number
);
3927 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3928 table
->num
= pRef
->number
>> 3;
3930 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3932 /* We don't want the first href to be 0 */
3933 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3935 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3937 unsigned int lib_offs
, type_num
;
3939 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3941 name
+= SLTG_ReadStringA(name
, &refname
);
3942 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3943 FIXME_(typelib
)("Can't sscanf ref\n");
3944 if(lib_offs
!= 0xffff) {
3947 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3948 if(import
->offset
== lib_offs
)
3951 if(&import
->entry
== &pTL
->implib_list
) {
3952 char fname
[MAX_PATH
+1];
3956 import
= heap_alloc_zero(sizeof(*import
));
3957 import
->offset
= lib_offs
;
3958 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3959 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3960 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3961 &import
->wVersionMajor
,
3962 &import
->wVersionMinor
,
3963 &import
->lcid
, fname
) != 4) {
3964 FIXME_(typelib
)("can't sscanf ref %s\n",
3965 pNameTable
+ lib_offs
+ 40);
3967 len
= strlen(fname
);
3968 if(fname
[len
-1] != '#')
3969 FIXME("fname = %s\n", fname
);
3970 fname
[len
-1] = '\0';
3971 import
->name
= TLB_MultiByteToBSTR(fname
);
3972 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3974 ref_type
->pImpTLInfo
= import
;
3976 /* Store a reference to IDispatch */
3977 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3978 pTL
->dispatch_href
= typelib_ref
;
3980 } else { /* internal ref */
3981 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3983 ref_type
->reference
= typelib_ref
;
3984 ref_type
->index
= type_num
;
3987 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3989 table
->refs
[ref
] = typelib_ref
;
3992 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3993 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3994 dump_TLBRefType(pTL
);
3998 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3999 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
4001 SLTG_ImplInfo
*info
;
4002 TLBImplType
*pImplType
;
4003 /* I don't really get this structure, usually it's 0x16 bytes
4004 long, but iuser.tlb contains some that are 0x18 bytes long.
4005 That's ok because we can use the next ptr to jump to the next
4006 one. But how do we know the length of the last one? The WORD
4007 at offs 0x8 might be the clue. For now I'm just assuming that
4008 the last one is the regular 0x16 bytes. */
4010 info
= (SLTG_ImplInfo
*)pBlk
;
4012 pTI
->typeattr
.cImplTypes
++;
4013 if(info
->next
== 0xffff)
4015 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4018 info
= (SLTG_ImplInfo
*)pBlk
;
4019 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
4020 pImplType
= pTI
->impltypes
;
4022 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4023 pImplType
->implflags
= info
->impltypeflags
;
4026 if(info
->next
== 0xffff)
4029 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4030 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4032 info
++; /* see comment at top of function */
4036 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4037 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4039 TLBVarDesc
*pVarDesc
;
4040 const TLBString
*prevName
= NULL
;
4041 SLTG_Variable
*pItem
;
4045 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4047 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4048 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4050 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4052 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4053 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4054 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4058 if (pItem
->name
== 0xfffe)
4059 pVarDesc
->Name
= prevName
;
4061 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4063 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4064 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4065 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4067 if(pItem
->flags
& 0x02)
4068 pType
= &pItem
->type
;
4070 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4072 if (pItem
->flags
& ~0xda)
4073 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4075 SLTG_DoElem(pType
, pBlk
,
4076 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4078 if (TRACE_ON(typelib
)) {
4080 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4081 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4084 if (pItem
->flags
& 0x40) {
4085 TRACE_(typelib
)("VAR_DISPATCH\n");
4086 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4088 else if (pItem
->flags
& 0x10) {
4089 TRACE_(typelib
)("VAR_CONST\n");
4090 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4091 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4092 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4093 if (pItem
->flags
& 0x08)
4094 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4096 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4102 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4104 TRACE_(typelib
)("len = %u\n", len
);
4105 if (len
== 0xffff) {
4108 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4109 str
= SysAllocStringLen(NULL
, alloc_len
);
4110 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4112 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4113 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4122 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4123 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4126 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4131 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4132 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4133 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4136 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4137 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4139 if (pItem
->flags
& 0x80)
4140 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4142 prevName
= pVarDesc
->Name
;
4144 pTI
->typeattr
.cVars
= cVars
;
4147 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4148 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4150 SLTG_Function
*pFunc
;
4152 TLBFuncDesc
*pFuncDesc
;
4154 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4156 pFuncDesc
= pTI
->funcdescs
;
4157 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4158 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4163 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4164 case SLTG_FUNCTION_MAGIC
:
4165 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4167 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4168 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4170 case SLTG_STATIC_FUNCTION_MAGIC
:
4171 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4174 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4177 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4179 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4180 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4181 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4182 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4183 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4184 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4186 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4187 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4189 if(pFunc
->retnextopt
& 0x80)
4190 pType
= &pFunc
->rettype
;
4192 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4194 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4196 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4197 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4198 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4200 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4202 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4203 char *paramName
= pNameTable
+ *pArg
;
4205 /* If arg type follows then paramName points to the 2nd
4206 letter of the name, else the next WORD is an offset to
4207 the arg type and paramName points to the first letter.
4208 So let's take one char off paramName and see if we're
4209 pointing at an alpha-numeric char. However if *pArg is
4210 0xffff or 0xfffe then the param has no name, the former
4211 meaning that the next WORD is the type, the latter
4212 meaning that the next WORD is an offset to the type. */
4217 else if(*pArg
== 0xfffe) {
4221 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4226 if(HaveOffs
) { /* the next word is an offset to type */
4227 pType
= (WORD
*)(pBlk
+ *pArg
);
4228 SLTG_DoElem(pType
, pBlk
,
4229 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4234 pArg
= SLTG_DoElem(pArg
, pBlk
,
4235 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4238 /* Are we an optional param ? */
4239 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4240 pFuncDesc
->funcdesc
.cParamsOpt
)
4241 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4244 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4245 paramName
- pNameTable
, pTI
->pTypeLib
);
4247 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4251 pTI
->typeattr
.cFuncs
= cFuncs
;
4254 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4255 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4256 SLTG_TypeInfoTail
*pTITail
)
4259 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4261 if(pTIHeader
->href_table
!= 0xffffffff) {
4262 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4268 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4269 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4271 heap_free(ref_lookup
);
4275 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4276 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4277 const SLTG_TypeInfoTail
*pTITail
)
4280 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4282 if(pTIHeader
->href_table
!= 0xffffffff) {
4283 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4289 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4290 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4293 if (pTITail
->funcs_off
!= 0xffff)
4294 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4296 heap_free(ref_lookup
);
4298 if (TRACE_ON(typelib
))
4299 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4302 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4303 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4304 const SLTG_TypeInfoTail
*pTITail
)
4306 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4309 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4310 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4311 const SLTG_TypeInfoTail
*pTITail
)
4314 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4316 if (pTITail
->simple_alias
) {
4317 /* if simple alias, no more processing required */
4318 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4319 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4323 if(pTIHeader
->href_table
!= 0xffffffff) {
4324 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4328 /* otherwise it is an offset to a type */
4329 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4331 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4332 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4334 heap_free(ref_lookup
);
4337 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4338 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4339 const SLTG_TypeInfoTail
*pTITail
)
4341 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4342 if (pTIHeader
->href_table
!= 0xffffffff)
4343 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4346 if (pTITail
->vars_off
!= 0xffff)
4347 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4349 if (pTITail
->funcs_off
!= 0xffff)
4350 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4352 if (pTITail
->impls_off
!= 0xffff)
4353 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4355 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4356 * of dispinterface functions including the IDispatch ones, so
4357 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4358 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4360 heap_free(ref_lookup
);
4361 if (TRACE_ON(typelib
))
4362 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4365 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4366 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4367 const SLTG_TypeInfoTail
*pTITail
)
4369 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4372 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4373 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4374 const SLTG_TypeInfoTail
*pTITail
)
4376 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4377 if (pTIHeader
->href_table
!= 0xffffffff)
4378 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4381 if (pTITail
->vars_off
!= 0xffff)
4382 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4384 if (pTITail
->funcs_off
!= 0xffff)
4385 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4386 heap_free(ref_lookup
);
4387 if (TRACE_ON(typelib
))
4391 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4392 manageable copy of it into this */
4405 } SLTG_InternalOtherTypeInfo
;
4407 /****************************************************************************
4408 * ITypeLib2_Constructor_SLTG
4410 * loading a SLTG typelib from an in-memory image
4412 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4414 ITypeLibImpl
*pTypeLibImpl
;
4415 SLTG_Header
*pHeader
;
4416 SLTG_BlkEntry
*pBlkEntry
;
4420 LPVOID pBlk
, pFirstBlk
;
4421 SLTG_LibBlk
*pLibBlk
;
4422 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4423 char *pAfterOTIBlks
= NULL
;
4424 char *pNameTable
, *ptr
;
4427 ITypeInfoImpl
**ppTypeInfoImpl
;
4429 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4432 pTypeLibImpl
= TypeLibImpl_Constructor();
4433 if (!pTypeLibImpl
) return NULL
;
4437 TRACE_(typelib
)("header:\n");
4438 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4439 pHeader
->nrOfFileBlks
);
4440 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4441 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4442 pHeader
->SLTG_magic
);
4446 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4447 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4449 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4450 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4452 /* Next we have a magic block */
4453 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4455 /* Let's see if we're still in sync */
4456 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4457 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4458 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4461 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4462 sizeof(SLTG_DIR_MAGIC
))) {
4463 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4467 pIndex
= (SLTG_Index
*)(pMagic
+1);
4469 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4471 pFirstBlk
= pPad9
+ 1;
4473 /* We'll set up a ptr to the main library block, which is the last one. */
4475 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4476 pBlkEntry
[order
].next
!= 0;
4477 order
= pBlkEntry
[order
].next
- 1) {
4478 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4482 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4484 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4489 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4491 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4494 ptr
= (char*)pLibBlk
+ len
;
4496 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4500 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4502 w
= *(WORD
*)(ptr
+ 2);
4505 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4506 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4507 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4509 w
= *(WORD
*)(ptr
+ 4 + len
);
4511 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4513 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4514 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4515 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4517 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4518 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4519 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4521 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4522 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4525 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4526 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4527 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4528 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4529 len
+= sizeof(SLTG_OtherTypeInfo
);
4533 pAfterOTIBlks
= ptr
;
4535 /* Skip this WORD and get the next DWORD */
4536 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4538 /* Now add this to pLibBLk look at what we're pointing at and
4539 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4540 dust and we should be pointing at the beginning of the name
4543 pNameTable
= (char*)pLibBlk
+ len
;
4545 switch(*(WORD
*)pNameTable
) {
4552 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4556 pNameTable
+= 0x216;
4560 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4562 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4565 /* Hopefully we now have enough ptrs set up to actually read in
4566 some TypeInfos. It's not clear which order to do them in, so
4567 I'll just follow the links along the BlkEntry chain and read
4568 them in the order in which they are in the file */
4570 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4571 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4573 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4574 pBlkEntry
[order
].next
!= 0;
4575 order
= pBlkEntry
[order
].next
- 1, i
++) {
4577 SLTG_TypeInfoHeader
*pTIHeader
;
4578 SLTG_TypeInfoTail
*pTITail
;
4579 SLTG_MemberHeader
*pMemHeader
;
4581 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4582 FIXME_(typelib
)("Index strings don't match\n");
4583 heap_free(pOtherTypeInfoBlks
);
4588 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4589 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4590 heap_free(pOtherTypeInfoBlks
);
4593 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4594 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4595 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4597 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4598 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4599 (*ppTypeInfoImpl
)->index
= i
;
4600 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4601 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4602 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4603 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4604 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4605 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4606 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4607 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4609 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4610 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4612 if((pTIHeader
->typeflags1
& 7) != 2)
4613 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4614 if(pTIHeader
->typeflags3
!= 2)
4615 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4617 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4618 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4619 typekind_desc
[pTIHeader
->typekind
],
4620 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4621 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4623 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4625 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4627 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4628 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4629 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4631 switch(pTIHeader
->typekind
) {
4633 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4634 pTIHeader
, pTITail
);
4638 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4639 pTIHeader
, pTITail
);
4642 case TKIND_INTERFACE
:
4643 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4644 pTIHeader
, pTITail
);
4648 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4649 pTIHeader
, pTITail
);
4653 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4654 pTIHeader
, pTITail
);
4657 case TKIND_DISPATCH
:
4658 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4659 pTIHeader
, pTITail
);
4663 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4664 pTIHeader
, pTITail
);
4668 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4673 /* could get cFuncs, cVars and cImplTypes from here
4674 but we've already set those */
4675 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4691 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4694 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4695 FIXME("Somehow processed %d TypeInfos\n", i
);
4696 heap_free(pOtherTypeInfoBlks
);
4700 heap_free(pOtherTypeInfoBlks
);
4701 return &pTypeLibImpl
->ITypeLib2_iface
;
4704 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4706 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4708 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4710 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4711 IsEqualIID(riid
,&IID_ITypeLib
)||
4712 IsEqualIID(riid
,&IID_ITypeLib2
))
4714 *ppv
= &This
->ITypeLib2_iface
;
4716 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4717 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4719 *ppv
= &This
->ICreateTypeLib2_iface
;
4724 TRACE("-- Interface: E_NOINTERFACE\n");
4725 return E_NOINTERFACE
;
4728 IUnknown_AddRef((IUnknown
*)*ppv
);
4732 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4734 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4735 ULONG ref
= InterlockedIncrement(&This
->ref
);
4737 TRACE("(%p) ref=%u\n", This
, ref
);
4742 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4744 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4745 ULONG ref
= InterlockedDecrement(&This
->ref
);
4747 TRACE("(%p) ref=%u\n",This
, ref
);
4751 TLBImpLib
*pImpLib
, *pImpLibNext
;
4752 TLBRefType
*ref_type
;
4753 TLBString
*tlbstr
, *tlbstr_next
;
4754 TLBGuid
*tlbguid
, *tlbguid_next
;
4758 /* remove cache entry */
4761 TRACE("removing from cache list\n");
4762 EnterCriticalSection(&cache_section
);
4763 if(This
->entry
.next
)
4764 list_remove(&This
->entry
);
4765 LeaveCriticalSection(&cache_section
);
4766 heap_free(This
->path
);
4768 TRACE(" destroying ITypeLib(%p)\n",This
);
4770 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4771 list_remove(&tlbstr
->entry
);
4772 SysFreeString(tlbstr
->str
);
4776 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4777 list_remove(&tlbstr
->entry
);
4778 SysFreeString(tlbstr
->str
);
4782 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4783 list_remove(&tlbguid
->entry
);
4787 TLB_FreeCustData(&This
->custdata_list
);
4789 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4790 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4791 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4793 heap_free(This
->pTypeDesc
);
4795 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4797 if (pImpLib
->pImpTypeLib
)
4798 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4799 SysFreeString(pImpLib
->name
);
4801 list_remove(&pImpLib
->entry
);
4805 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4807 list_remove(&ref_type
->entry
);
4808 heap_free(ref_type
);
4811 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4812 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4813 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4815 heap_free(This
->typeinfos
);
4823 /* ITypeLib::GetTypeInfoCount
4825 * Returns the number of type descriptions in the type library
4827 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4829 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4830 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4831 return This
->TypeInfoCount
;
4834 /* ITypeLib::GetTypeInfo
4836 * retrieves the specified type description in the library.
4838 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4841 ITypeInfo
**ppTInfo
)
4843 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4845 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4848 return E_INVALIDARG
;
4850 if(index
>= This
->TypeInfoCount
)
4851 return TYPE_E_ELEMENTNOTFOUND
;
4853 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4854 ITypeInfo_AddRef(*ppTInfo
);
4860 /* ITypeLibs::GetTypeInfoType
4862 * Retrieves the type of a type description.
4864 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4869 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4871 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4874 return E_INVALIDARG
;
4876 if(index
>= This
->TypeInfoCount
)
4877 return TYPE_E_ELEMENTNOTFOUND
;
4879 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4884 /* ITypeLib::GetTypeInfoOfGuid
4886 * Retrieves the type description that corresponds to the specified GUID.
4889 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4892 ITypeInfo
**ppTInfo
)
4894 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4897 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4899 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4900 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4901 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4902 ITypeInfo_AddRef(*ppTInfo
);
4907 return TYPE_E_ELEMENTNOTFOUND
;
4910 /* ITypeLib::GetLibAttr
4912 * Retrieves the structure that contains the library's attributes.
4915 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4919 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4921 TRACE("(%p, %p)\n", This
, attr
);
4923 if (!attr
) return E_INVALIDARG
;
4925 *attr
= heap_alloc(sizeof(**attr
));
4926 if (!*attr
) return E_OUTOFMEMORY
;
4928 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4929 (*attr
)->lcid
= This
->set_lcid
;
4930 (*attr
)->syskind
= This
->syskind
;
4931 (*attr
)->wMajorVerNum
= This
->ver_major
;
4932 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4933 (*attr
)->wLibFlags
= This
->libflags
;
4938 /* ITypeLib::GetTypeComp
4940 * Enables a client compiler to bind to a library's types, variables,
4941 * constants, and global functions.
4944 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4946 ITypeComp
**ppTComp
)
4948 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4950 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4951 *ppTComp
= &This
->ITypeComp_iface
;
4952 ITypeComp_AddRef(*ppTComp
);
4957 /* ITypeLib::GetDocumentation
4959 * Retrieves the library's documentation string, the complete Help file name
4960 * and path, and the context identifier for the library Help topic in the Help
4963 * On a successful return all non-null BSTR pointers will have been set,
4966 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4970 BSTR
*pBstrDocString
,
4971 DWORD
*pdwHelpContext
,
4972 BSTR
*pBstrHelpFile
)
4974 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4975 HRESULT result
= E_INVALIDARG
;
4978 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4980 pBstrName
, pBstrDocString
,
4981 pdwHelpContext
, pBstrHelpFile
);
4985 /* documentation for the typelib */
4990 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4998 if (This
->DocString
)
5000 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
5004 *pBstrDocString
= NULL
;
5008 *pdwHelpContext
= This
->dwHelpContext
;
5014 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5018 *pBstrHelpFile
= NULL
;
5025 /* for a typeinfo */
5026 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5028 if(SUCCEEDED(result
))
5030 result
= ITypeInfo_GetDocumentation(pTInfo
,
5034 pdwHelpContext
, pBstrHelpFile
);
5036 ITypeInfo_Release(pTInfo
);
5041 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5043 if (pBstrName
) SysFreeString (*pBstrName
);
5045 return STG_E_INSUFFICIENTMEMORY
;
5050 * Indicates whether a passed-in string contains the name of a type or member
5051 * described in the library.
5054 static HRESULT WINAPI
ITypeLib2_fnIsName(
5060 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5062 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5064 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5068 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5069 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5070 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5071 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5072 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5074 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5075 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5076 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5077 goto ITypeLib2_fnIsName_exit
;
5080 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5081 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5082 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5088 ITypeLib2_fnIsName_exit
:
5089 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5090 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5095 /* ITypeLib::FindName
5097 * Finds occurrences of a type description in a type library. This may be used
5098 * to quickly verify that a name exists in a type library.
5101 static HRESULT WINAPI
ITypeLib2_fnFindName(
5105 ITypeInfo
**ppTInfo
,
5109 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5114 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5116 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5117 return E_INVALIDARG
;
5119 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5120 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5121 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5125 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5126 memid
[count
] = MEMBERID_NIL
;
5127 goto ITypeLib2_fnFindName_exit
;
5130 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5131 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5133 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5134 memid
[count
] = func
->funcdesc
.memid
;
5135 goto ITypeLib2_fnFindName_exit
;
5139 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->typeattr
.cVars
, name
);
5141 memid
[count
] = var
->vardesc
.memid
;
5142 goto ITypeLib2_fnFindName_exit
;
5146 ITypeLib2_fnFindName_exit
:
5147 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5148 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5151 TRACE("found %d typeinfos\n", count
);
5158 /* ITypeLib::ReleaseTLibAttr
5160 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5163 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5165 TLIBATTR
*pTLibAttr
)
5167 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5168 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5169 heap_free(pTLibAttr
);
5172 /* ITypeLib2::GetCustData
5174 * gets the custom data
5176 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5181 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5182 TLBCustData
*pCData
;
5184 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5186 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5188 return TYPE_E_ELEMENTNOTFOUND
;
5190 VariantInit(pVarVal
);
5191 VariantCopy(pVarVal
, &pCData
->data
);
5196 /* ITypeLib2::GetLibStatistics
5198 * Returns statistics about a type library that are required for efficient
5199 * sizing of hash tables.
5202 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5204 ULONG
*pcUniqueNames
,
5205 ULONG
*pcchUniqueNames
)
5207 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5209 FIXME("(%p): stub!\n", This
);
5211 if(pcUniqueNames
) *pcUniqueNames
=1;
5212 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5216 /* ITypeLib2::GetDocumentation2
5218 * Retrieves the library's documentation string, the complete Help file name
5219 * and path, the localization context to use, and the context ID for the
5220 * library Help topic in the Help file.
5223 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5227 BSTR
*pbstrHelpString
,
5228 DWORD
*pdwHelpStringContext
,
5229 BSTR
*pbstrHelpStringDll
)
5231 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5235 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5237 /* the help string should be obtained from the helpstringdll,
5238 * using the _DLLGetDocumentation function, based on the supplied
5239 * lcid. Nice to do sometime...
5243 /* documentation for the typelib */
5245 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5246 if(pdwHelpStringContext
)
5247 *pdwHelpStringContext
=This
->dwHelpContext
;
5248 if(pbstrHelpStringDll
)
5249 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5255 /* for a typeinfo */
5256 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5258 if(SUCCEEDED(result
))
5260 ITypeInfo2
* pTInfo2
;
5261 result
= ITypeInfo_QueryInterface(pTInfo
,
5263 (LPVOID
*) &pTInfo2
);
5265 if(SUCCEEDED(result
))
5267 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5271 pdwHelpStringContext
,
5272 pbstrHelpStringDll
);
5274 ITypeInfo2_Release(pTInfo2
);
5277 ITypeInfo_Release(pTInfo
);
5283 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5285 TLBCustData
*pCData
;
5289 ct
= list_count(custdata_list
);
5291 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5292 if(!pCustData
->prgCustData
)
5293 return E_OUTOFMEMORY
;
5295 pCustData
->cCustData
= ct
;
5297 cdi
= pCustData
->prgCustData
;
5298 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5299 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5300 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5308 /* ITypeLib2::GetAllCustData
5310 * Gets all custom data items for the library.
5313 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5315 CUSTDATA
*pCustData
)
5317 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5318 TRACE("(%p)->(%p)\n", This
, pCustData
);
5319 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5322 static const ITypeLib2Vtbl tlbvt
= {
5323 ITypeLib2_fnQueryInterface
,
5325 ITypeLib2_fnRelease
,
5326 ITypeLib2_fnGetTypeInfoCount
,
5327 ITypeLib2_fnGetTypeInfo
,
5328 ITypeLib2_fnGetTypeInfoType
,
5329 ITypeLib2_fnGetTypeInfoOfGuid
,
5330 ITypeLib2_fnGetLibAttr
,
5331 ITypeLib2_fnGetTypeComp
,
5332 ITypeLib2_fnGetDocumentation
,
5334 ITypeLib2_fnFindName
,
5335 ITypeLib2_fnReleaseTLibAttr
,
5337 ITypeLib2_fnGetCustData
,
5338 ITypeLib2_fnGetLibStatistics
,
5339 ITypeLib2_fnGetDocumentation2
,
5340 ITypeLib2_fnGetAllCustData
5344 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5346 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5348 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5351 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5353 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5355 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5358 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5360 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5362 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5365 static HRESULT WINAPI
ITypeLibComp_fnBind(
5370 ITypeInfo
** ppTInfo
,
5371 DESCKIND
* pDescKind
,
5374 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5375 BOOL typemismatch
= FALSE
;
5378 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5380 *pDescKind
= DESCKIND_NONE
;
5381 pBindPtr
->lptcomp
= NULL
;
5384 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5385 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5386 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5388 /* FIXME: check wFlags here? */
5389 /* FIXME: we should use a hash table to look this info up using lHash
5390 * instead of an O(n) search */
5391 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5392 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5394 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5396 *pDescKind
= DESCKIND_TYPECOMP
;
5397 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5398 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5399 TRACE("module or enum: %s\n", debugstr_w(szName
));
5404 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5405 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5407 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5410 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5411 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5413 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5416 else if (hr
== TYPE_E_TYPEMISMATCH
)
5417 typemismatch
= TRUE
;
5420 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5421 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5423 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5425 ITypeInfo
*subtypeinfo
;
5427 DESCKIND subdesckind
;
5429 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5430 &subtypeinfo
, &subdesckind
, &subbindptr
);
5431 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5433 TYPEDESC tdesc_appobject
;
5434 const VARDESC vardesc_appobject
=
5437 NULL
, /* lpstrSchema */
5452 VAR_STATIC
/* varkind */
5455 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5456 tdesc_appobject
.vt
= VT_USERDEFINED
;
5458 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5460 /* cleanup things filled in by Bind call so we can put our
5461 * application object data in there instead */
5462 switch (subdesckind
)
5464 case DESCKIND_FUNCDESC
:
5465 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5467 case DESCKIND_VARDESC
:
5468 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5473 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5475 if (pTypeInfo
->hreftype
== -1)
5476 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5478 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5482 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5483 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5484 ITypeInfo_AddRef(*ppTInfo
);
5487 else if (hr
== TYPE_E_TYPEMISMATCH
)
5488 typemismatch
= TRUE
;
5494 TRACE("type mismatch %s\n", debugstr_w(szName
));
5495 return TYPE_E_TYPEMISMATCH
;
5499 TRACE("name not found %s\n", debugstr_w(szName
));
5504 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5508 ITypeInfo
** ppTInfo
,
5509 ITypeComp
** ppTComp
)
5511 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5512 ITypeInfoImpl
*info
;
5514 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5516 if(!szName
|| !ppTInfo
|| !ppTComp
)
5517 return E_INVALIDARG
;
5519 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5526 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5527 ITypeInfo_AddRef(*ppTInfo
);
5528 *ppTComp
= &info
->ITypeComp_iface
;
5529 ITypeComp_AddRef(*ppTComp
);
5534 static const ITypeCompVtbl tlbtcvt
=
5537 ITypeLibComp_fnQueryInterface
,
5538 ITypeLibComp_fnAddRef
,
5539 ITypeLibComp_fnRelease
,
5541 ITypeLibComp_fnBind
,
5542 ITypeLibComp_fnBindType
5545 /*================== ITypeInfo(2) Methods ===================================*/
5546 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5548 ITypeInfoImpl
*pTypeInfoImpl
;
5550 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5553 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5554 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5555 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5556 pTypeInfoImpl
->ref
= 0;
5557 pTypeInfoImpl
->hreftype
= -1;
5558 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5559 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5560 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5561 list_init(pTypeInfoImpl
->pcustdata_list
);
5563 TRACE("(%p)\n", pTypeInfoImpl
);
5564 return pTypeInfoImpl
;
5567 /* ITypeInfo::QueryInterface
5569 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5574 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5576 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5579 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5580 IsEqualIID(riid
,&IID_ITypeInfo
)||
5581 IsEqualIID(riid
,&IID_ITypeInfo2
))
5583 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5584 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5585 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5586 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5587 *ppvObject
= &This
->ITypeComp_iface
;
5590 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5591 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5594 TRACE("-- Interface: E_NOINTERFACE\n");
5595 return E_NOINTERFACE
;
5598 /* ITypeInfo::AddRef
5600 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5602 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5603 ULONG ref
= InterlockedIncrement(&This
->ref
);
5605 TRACE("(%p)->ref is %u\n",This
, ref
);
5607 if (ref
== 1 /* incremented from 0 */)
5608 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5613 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5617 TRACE("destroying ITypeInfo(%p)\n",This
);
5619 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5622 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5623 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5625 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5626 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5627 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5628 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5630 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5631 heap_free(pFInfo
->pParamDesc
);
5632 TLB_FreeCustData(&pFInfo
->custdata_list
);
5634 heap_free(This
->funcdescs
);
5636 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5638 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5639 if (pVInfo
->vardesc_create
) {
5640 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5641 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5642 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5643 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5645 TLB_FreeCustData(&pVInfo
->custdata_list
);
5647 heap_free(This
->vardescs
);
5649 if(This
->impltypes
){
5650 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5651 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5652 TLB_FreeCustData(&pImpl
->custdata_list
);
5654 heap_free(This
->impltypes
);
5657 TLB_FreeCustData(&This
->custdata_list
);
5662 /* ITypeInfo::Release
5664 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5666 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5667 ULONG ref
= InterlockedDecrement(&This
->ref
);
5669 TRACE("(%p)->(%u)\n",This
, ref
);
5673 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5674 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5675 if (not_attached_to_typelib
)
5677 /* otherwise This will be freed when typelib is freed */
5683 /* ITypeInfo::GetTypeAttr
5685 * Retrieves a TYPEATTR structure that contains the attributes of the type
5689 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5690 LPTYPEATTR
*ppTypeAttr
)
5692 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5695 TRACE("(%p)\n",This
);
5697 size
= sizeof(**ppTypeAttr
);
5698 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5699 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5701 *ppTypeAttr
= heap_alloc(size
);
5703 return E_OUTOFMEMORY
;
5705 **ppTypeAttr
= This
->typeattr
;
5706 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5708 if (This
->tdescAlias
)
5709 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5711 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5712 /* This should include all the inherited funcs */
5713 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5714 /* This is always the size of IDispatch's vtbl */
5715 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5716 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5721 /* ITypeInfo::GetTypeComp
5723 * Retrieves the ITypeComp interface for the type description, which enables a
5724 * client compiler to bind to the type description's members.
5727 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5728 ITypeComp
* *ppTComp
)
5730 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5732 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5734 *ppTComp
= &This
->ITypeComp_iface
;
5735 ITypeComp_AddRef(*ppTComp
);
5739 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5741 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5742 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5743 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5747 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5750 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5751 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5753 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5754 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5755 *buffer
+= sizeof(PARAMDESCEX
);
5756 *pparamdescex_dest
= *pparamdescex_src
;
5757 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5758 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5759 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5760 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5763 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5767 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5769 UINT len
= SysStringLen(str
), i
;
5770 for (i
= 0; i
< len
; ++i
)
5776 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5778 if (V_VT(var
) == VT_INT
)
5779 return VariantChangeType(var
, var
, 0, VT_I4
);
5780 else if (V_VT(var
) == VT_UINT
)
5781 return VariantChangeType(var
, var
, 0, VT_UI4
);
5782 else if (V_VT(var
) == VT_BSTR
)
5783 return TLB_SanitizeBSTR(V_BSTR(var
));
5788 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5790 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5791 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5794 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5798 SIZE_T size
= sizeof(*src
);
5802 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5803 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5804 for (i
= 0; i
< src
->cParams
; i
++)
5806 size
+= sizeof(ELEMDESC
);
5807 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5810 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5811 if (!dest
) return E_OUTOFMEMORY
;
5814 if (dispinterface
) /* overwrite funckind */
5815 dest
->funckind
= FUNC_DISPATCH
;
5816 buffer
= (char *)(dest
+ 1);
5818 dest
->oVft
= dest
->oVft
& 0xFFFC;
5820 if (dest
->cScodes
) {
5821 dest
->lprgscode
= (SCODE
*)buffer
;
5822 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5823 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5825 dest
->lprgscode
= NULL
;
5827 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5830 SysFreeString((BSTR
)dest
);
5834 if (dest
->cParams
) {
5835 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5836 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5837 for (i
= 0; i
< src
->cParams
; i
++)
5839 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5845 /* undo the above actions */
5846 for (i
= i
- 1; i
>= 0; i
--)
5847 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5848 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5849 SysFreeString((BSTR
)dest
);
5853 dest
->lprgelemdescParam
= NULL
;
5855 /* special treatment for dispinterfaces: this makes functions appear
5856 * to return their [retval] value when it is really returning an
5858 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5860 if (dest
->cParams
&&
5861 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5863 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5864 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5866 ERR("elemdesc should have started with VT_PTR instead of:\n");
5868 dump_ELEMDESC(elemdesc
);
5869 return E_UNEXPECTED
;
5872 /* copy last parameter to the return value. we are using a flat
5873 * buffer so there is no danger of leaking memory in
5875 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5877 /* remove the last parameter */
5881 /* otherwise this function is made to appear to have no return
5883 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5891 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5893 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5894 if (var_desc
->varkind
== VAR_CONST
)
5895 VariantClear(var_desc
->u
.lpvarValue
);
5896 SysFreeString((BSTR
)var_desc
);
5899 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5901 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5903 if (index
>= This
->typeattr
.cFuncs
)
5904 return TYPE_E_ELEMENTNOTFOUND
;
5906 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5910 /* internal function to make the inherited interfaces' methods appear
5911 * part of the interface */
5912 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5913 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5915 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5917 UINT implemented_funcs
= 0;
5922 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5926 ITypeInfo
*pSubTypeInfo
;
5929 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5933 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5936 &sub_funcs
, hrefoffset
);
5937 implemented_funcs
+= sub_funcs
;
5938 ITypeInfo_Release(pSubTypeInfo
);
5941 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5945 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5949 if (index
< implemented_funcs
)
5950 return E_INVALIDARG
;
5951 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5955 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5957 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5960 switch (pTypeDesc
->vt
)
5962 case VT_USERDEFINED
:
5963 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5967 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5970 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5978 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5981 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5982 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5983 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5986 /* ITypeInfo::GetFuncDesc
5988 * Retrieves the FUNCDESC structure that contains information about a
5989 * specified function.
5992 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5993 LPFUNCDESC
*ppFuncDesc
)
5995 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5996 const FUNCDESC
*internal_funcdesc
;
5998 UINT hrefoffset
= 0;
6000 TRACE("(%p) index %d\n", This
, index
);
6003 return E_INVALIDARG
;
6005 if (This
->needs_layout
)
6006 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6008 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
6009 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
6010 &internal_funcdesc
, NULL
,
6013 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6014 &internal_funcdesc
);
6017 WARN("description for function %d not found\n", index
);
6021 hr
= TLB_AllocAndInitFuncDesc(
6024 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6026 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
6027 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6029 TRACE("-- 0x%08x\n", hr
);
6033 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6037 SIZE_T size
= sizeof(*src
);
6040 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6041 if (src
->varkind
== VAR_CONST
)
6042 size
+= sizeof(VARIANT
);
6043 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6045 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6046 if (!dest
) return E_OUTOFMEMORY
;
6049 buffer
= (char *)(dest
+ 1);
6050 if (src
->lpstrSchema
)
6053 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6054 len
= strlenW(src
->lpstrSchema
);
6055 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6056 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6059 if (src
->varkind
== VAR_CONST
)
6063 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6064 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6065 buffer
+= sizeof(VARIANT
);
6066 VariantInit(dest
->u
.lpvarValue
);
6067 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6070 SysFreeString((BSTR
)dest
);
6074 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6077 if (src
->varkind
== VAR_CONST
)
6078 VariantClear(dest
->u
.lpvarValue
);
6079 SysFreeString((BSTR
)dest
);
6086 /* ITypeInfo::GetVarDesc
6088 * Retrieves a VARDESC structure that describes the specified variable.
6091 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6092 LPVARDESC
*ppVarDesc
)
6094 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6095 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6097 TRACE("(%p) index %d\n", This
, index
);
6099 if(index
>= This
->typeattr
.cVars
)
6100 return TYPE_E_ELEMENTNOTFOUND
;
6102 if (This
->needs_layout
)
6103 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6105 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6108 /* ITypeInfo_GetNames
6110 * Retrieves the variable with the specified member ID (or the name of the
6111 * property or method and its parameters) that correspond to the specified
6114 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6115 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6117 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6118 const TLBFuncDesc
*pFDesc
;
6119 const TLBVarDesc
*pVDesc
;
6121 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6124 return E_INVALIDARG
;
6128 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
6131 if(!cMaxNames
|| !pFDesc
->Name
)
6134 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6137 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6138 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6140 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6146 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
6149 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6154 if(This
->impltypes
&&
6155 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
6156 /* recursive search */
6159 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6160 if(SUCCEEDED(result
))
6162 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6163 ITypeInfo_Release(pTInfo
);
6166 WARN("Could not search inherited interface!\n");
6170 WARN("no names found\n");
6173 return TYPE_E_ELEMENTNOTFOUND
;
6179 /* ITypeInfo::GetRefTypeOfImplType
6181 * If a type description describes a COM class, it retrieves the type
6182 * description of the implemented interface types. For an interface,
6183 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6187 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6192 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6195 TRACE("(%p) index %d\n", This
, index
);
6196 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6200 /* only valid on dual interfaces;
6201 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6204 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6210 hr
= TYPE_E_ELEMENTNOTFOUND
;
6213 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6215 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6216 *pRefType
= This
->pTypeLib
->dispatch_href
;
6220 if(index
>= This
->typeattr
.cImplTypes
)
6221 hr
= TYPE_E_ELEMENTNOTFOUND
;
6223 *pRefType
= This
->impltypes
[index
].hRef
;
6224 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6232 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6234 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6240 /* ITypeInfo::GetImplTypeFlags
6242 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6243 * or base interface in a type description.
6245 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6246 UINT index
, INT
*pImplTypeFlags
)
6248 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6250 TRACE("(%p) index %d\n", This
, index
);
6253 return E_INVALIDARG
;
6255 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6256 *pImplTypeFlags
= 0;
6260 if(index
>= This
->typeattr
.cImplTypes
)
6261 return TYPE_E_ELEMENTNOTFOUND
;
6263 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6269 * Maps between member names and member IDs, and parameter names and
6272 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6273 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6275 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6276 const TLBVarDesc
*pVDesc
;
6280 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6283 /* init out parameters in case of failure */
6284 for (i
= 0; i
< cNames
; i
++)
6285 pMemId
[i
] = MEMBERID_NIL
;
6287 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6289 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6290 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6291 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6292 for(i
=1; i
< cNames
; i
++){
6293 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6294 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6296 if( j
<pFDesc
->funcdesc
.cParams
)
6299 ret
=DISP_E_UNKNOWNNAME
;
6301 TRACE("-- 0x%08x\n", ret
);
6305 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, *rgszNames
);
6308 *pMemId
= pVDesc
->vardesc
.memid
;
6311 /* not found, see if it can be found in an inherited interface */
6312 if(This
->impltypes
) {
6313 /* recursive search */
6315 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6317 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6318 ITypeInfo_Release(pTInfo
);
6321 WARN("Could not search inherited interface!\n");
6323 WARN("no names found\n");
6324 return DISP_E_UNKNOWNNAME
;
6330 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6331 __ASM_GLOBAL_FUNC( call_method
,
6333 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6334 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6335 "movl %esp,%ebp\n\t"
6336 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6338 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6340 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6341 "movl 12(%ebp),%edx\n\t"
6342 "movl %esp,%edi\n\t"
6345 "subl %edx,%edi\n\t"
6346 "andl $~15,%edi\n\t"
6347 "movl %edi,%esp\n\t"
6348 "movl 12(%ebp),%ecx\n\t"
6349 "movl 16(%ebp),%esi\n\t"
6352 "1:\tcall *8(%ebp)\n\t"
6353 "subl %esp,%edi\n\t"
6354 "movl 20(%ebp),%ecx\n\t"
6355 "movl %edi,(%ecx)\n\t"
6356 "leal -8(%ebp),%esp\n\t"
6358 __ASM_CFI(".cfi_same_value %edi\n\t")
6360 __ASM_CFI(".cfi_same_value %esi\n\t")
6362 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6363 __ASM_CFI(".cfi_same_value %ebp\n\t")
6366 /* same function but returning floating point */
6367 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6369 /* ITypeInfo::Invoke
6371 * Invokes a method, or accesses a property of an object, that implements the
6372 * interface described by the type description.
6375 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6379 if (TRACE_ON(ole
)) {
6381 TRACE("Calling %p(",func
);
6382 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6383 if (nrargs
> 30) TRACE("...");
6390 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6393 FIXME("unsupported calling convention %d\n",callconv
);
6397 TRACE("returns %08x\n",res
);
6401 #elif defined(__x86_64__)
6403 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6404 __ASM_GLOBAL_FUNC( call_method
,
6406 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6407 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6408 "movq %rsp,%rbp\n\t"
6409 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6411 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6413 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6414 "movq %rcx,%rax\n\t"
6417 "cmovgq %rdx,%rcx\n\t"
6418 "leaq 0(,%rcx,8),%rdx\n\t"
6419 "subq %rdx,%rsp\n\t"
6420 "andq $~15,%rsp\n\t"
6421 "movq %rsp,%rdi\n\t"
6424 "movq 0(%rsp),%rcx\n\t"
6425 "movq 8(%rsp),%rdx\n\t"
6426 "movq 16(%rsp),%r8\n\t"
6427 "movq 24(%rsp),%r9\n\t"
6428 "movq 0(%rsp),%xmm0\n\t"
6429 "movq 8(%rsp),%xmm1\n\t"
6430 "movq 16(%rsp),%xmm2\n\t"
6431 "movq 24(%rsp),%xmm3\n\t"
6433 "leaq -16(%rbp),%rsp\n\t"
6435 __ASM_CFI(".cfi_same_value %rdi\n\t")
6437 __ASM_CFI(".cfi_same_value %rsi\n\t")
6438 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6440 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6441 __ASM_CFI(".cfi_same_value %rbp\n\t")
6444 /* same function but returning floating point */
6445 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6447 #endif /* __x86_64__ */
6449 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6452 ITypeInfo
*tinfo2
= NULL
;
6453 TYPEATTR
*tattr
= NULL
;
6455 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6458 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6460 tdesc
->u
.hreftype
, hr
);
6463 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6466 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6467 ITypeInfo_Release(tinfo2
);
6471 switch (tattr
->typekind
)
6478 tdesc
= &tattr
->tdescAlias
;
6479 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6482 case TKIND_INTERFACE
:
6483 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6489 case TKIND_DISPATCH
:
6498 FIXME("TKIND_RECORD unhandled.\n");
6503 FIXME("TKIND_UNION unhandled.\n");
6508 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6512 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6513 ITypeInfo_Release(tinfo2
);
6517 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6521 /* enforce only one level of pointer indirection */
6522 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6524 tdesc
= tdesc
->u
.lptdesc
;
6526 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6527 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6528 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6529 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6530 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6532 VARTYPE vt_userdefined
= 0;
6533 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6534 if (tdesc
->vt
== VT_PTR
)
6536 vt_userdefined
= VT_BYREF
;
6537 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6539 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6541 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6542 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6544 *vt
|= vt_userdefined
;
6556 case VT_USERDEFINED
:
6557 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6564 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6565 hr
= DISP_E_BADVARTYPE
;
6569 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6584 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6590 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6594 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6596 ITypeInfo_Release(tinfo2
);
6600 switch(tattr
->typekind
) {
6602 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6605 case TKIND_INTERFACE
:
6606 case TKIND_DISPATCH
:
6607 *guid
= tattr
->guid
;
6611 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6612 hres
= E_UNEXPECTED
;
6615 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6616 ITypeInfo_Release(tinfo2
);
6620 /***********************************************************************
6621 * DispCallFunc (OLEAUT32.@)
6623 * Invokes a function of the specified calling convention, passing the
6624 * specified arguments and returns the result.
6627 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6628 * oVft [I] The offset in the vtable. See notes.
6629 * cc [I] Calling convention of the function to call.
6630 * vtReturn [I] The return type of the function.
6631 * cActuals [I] Number of parameters.
6632 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6633 * prgpvarg [I] The arguments to pass.
6634 * pvargResult [O] The return value of the function. Can be NULL.
6638 * Failure: HRESULT code.
6641 * The HRESULT return value of this function is not affected by the return
6642 * value of the user supplied function, which is returned in pvargResult.
6644 * If pvInstance is NULL then a non-object function is to be called and oVft
6645 * is the address of the function to call.
6647 * The cc parameter can be one of the following values:
6660 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6661 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6664 int argspos
, stack_offset
;
6669 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6670 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6671 pvargResult
, V_VT(pvargResult
));
6673 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6675 FIXME("unsupported calling convention %d\n",cc
);
6676 return E_INVALIDARG
;
6679 /* maximum size for an argument is sizeof(VARIANT) */
6680 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6682 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6686 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6687 func
= vtable
[oVft
/sizeof(void *)];
6688 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6690 else func
= (void *)oVft
;
6692 for (i
= 0; i
< cActuals
; i
++)
6694 VARIANT
*arg
= prgpvarg
[i
];
6705 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6706 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6710 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6711 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6713 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6714 args
[argspos
++] = V_BOOL(arg
);
6717 args
[argspos
++] = V_UI4(arg
);
6720 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6726 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6729 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6733 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6737 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6738 call_method( func
, argspos
, args
, &stack_offset
);
6743 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6746 WARN("invalid return type %u\n", vtReturn
);
6748 return E_INVALIDARG
;
6750 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6754 if (stack_offset
&& cc
== CC_STDCALL
)
6756 WARN( "stack pointer off by %d\n", stack_offset
);
6757 return DISP_E_BADCALLEE
;
6759 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6760 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6763 #elif defined(__x86_64__)
6769 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6770 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6771 pvargResult
, V_VT(pvargResult
));
6773 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6775 FIXME("unsupported calling convention %d\n",cc
);
6776 return E_INVALIDARG
;
6779 /* maximum size for an argument is sizeof(DWORD_PTR) */
6780 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6782 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6786 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6787 func
= vtable
[oVft
/sizeof(void *)];
6788 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6790 else func
= (void *)oVft
;
6792 for (i
= 0; i
< cActuals
; i
++)
6794 VARIANT
*arg
= prgpvarg
[i
];
6800 args
[argspos
++] = (ULONG_PTR
)arg
;
6802 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6803 args
[argspos
++] = V_BOOL(arg
);
6806 args
[argspos
++] = V_UI8(arg
);
6809 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6815 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6819 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6823 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6824 call_method( func
, argspos
, args
);
6827 WARN("invalid return type %u\n", vtReturn
);
6829 return E_INVALIDARG
;
6831 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6835 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6836 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6840 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6841 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6846 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6848 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6851 #define INVBUF_ELEMENT_SIZE \
6852 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6853 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6854 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6855 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6856 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6857 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6858 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6859 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6861 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6866 DISPPARAMS
*pDispParams
,
6867 VARIANT
*pVarResult
,
6868 EXCEPINFO
*pExcepInfo
,
6871 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6873 unsigned int var_index
;
6876 const TLBFuncDesc
*pFuncInfo
;
6879 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6880 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6883 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6884 return DISP_E_MEMBERNOTFOUND
;
6888 ERR("NULL pDispParams not allowed\n");
6889 return E_INVALIDARG
;
6892 dump_DispParms(pDispParams
);
6894 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6896 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6897 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6898 return E_INVALIDARG
;
6901 /* we do this instead of using GetFuncDesc since it will return a fake
6902 * FUNCDESC for dispinterfaces and we want the real function description */
6903 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
6904 pFuncInfo
= &This
->funcdescs
[fdc
];
6905 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6906 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6907 !func_restricted( &pFuncInfo
->funcdesc
))
6911 if (fdc
< This
->typeattr
.cFuncs
) {
6912 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6916 TRACE("invoking:\n");
6917 dump_TLBFuncDescOne(pFuncInfo
);
6920 switch (func_desc
->funckind
) {
6921 case FUNC_PUREVIRTUAL
:
6922 case FUNC_VIRTUAL
: {
6923 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6925 VARIANT retval
; /* pointer for storing byref retvals in */
6926 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6927 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6928 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6929 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6930 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6931 UINT vargs_converted
=0;
6935 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6937 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6939 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6940 hres
= DISP_E_PARAMNOTFOUND
;
6945 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6947 ERR("functions with the vararg attribute do not support named arguments\n");
6948 hres
= DISP_E_NONAMEDARGS
;
6952 for (i
= 0; i
< func_desc
->cParams
; i
++)
6954 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6955 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6960 TRACE("changing args\n");
6961 for (i
= 0; i
< func_desc
->cParams
; i
++)
6963 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6964 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6965 VARIANTARG
*src_arg
;
6967 if (wParamFlags
& PARAMFLAG_FLCID
)
6970 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6972 V_I4(arg
) = This
->pTypeLib
->lcid
;
6981 for (j
= 0; j
< cNamedArgs
; j
++)
6982 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6984 src_arg
= &pDispParams
->rgvarg
[j
];
6989 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6991 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6995 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6997 /* under most conditions the caller is not allowed to
6998 * pass in a dispparam arg in the index of what would be
6999 * the retval parameter. however, there is an exception
7000 * where the extra parameter is used in an extra
7001 * IDispatch::Invoke below */
7002 if ((i
< pDispParams
->cArgs
) &&
7003 ((func_desc
->cParams
!= 1) || !pVarResult
||
7004 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7006 hres
= DISP_E_BADPARAMCOUNT
;
7010 /* note: this check is placed so that if the caller passes
7011 * in a VARIANTARG for the retval we just ignore it, like
7013 if (i
== func_desc
->cParams
- 1)
7016 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7017 memset(arg
, 0, sizeof(*arg
));
7018 V_VT(arg
) = rgvt
[i
];
7019 memset(&retval
, 0, sizeof(retval
));
7020 V_BYREF(arg
) = &retval
;
7024 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7025 hres
= E_UNEXPECTED
;
7031 TRACE("%s\n", debugstr_variant(src_arg
));
7033 if(rgvt
[i
]!=V_VT(src_arg
))
7035 if (rgvt
[i
] == VT_VARIANT
)
7036 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7037 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7039 if (rgvt
[i
] == V_VT(src_arg
))
7040 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7043 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7044 if (wParamFlags
& PARAMFLAG_FIN
)
7045 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7046 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7048 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7050 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7053 SAFEARRAYBOUND bound
;
7057 bound
.cElements
= pDispParams
->cArgs
-i
;
7058 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7060 ERR("SafeArrayCreate failed\n");
7063 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7066 ERR("SafeArrayAccessData failed with %x\n", hres
);
7067 SafeArrayDestroy(a
);
7070 for (j
= 0; j
< bound
.cElements
; j
++)
7071 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7072 hres
= SafeArrayUnaccessData(a
);
7075 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7076 SafeArrayDestroy(a
);
7079 if (rgvt
[i
] & VT_BYREF
)
7080 V_BYREF(&rgvarg
[i
]) = &a
;
7082 V_ARRAY(&rgvarg
[i
]) = a
;
7083 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7085 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7087 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7088 if (wParamFlags
& PARAMFLAG_FIN
)
7089 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7091 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7092 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7093 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7095 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7097 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7098 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7102 /* FIXME: this doesn't work for VT_BYREF arguments if
7103 * they are not the same type as in the paramdesc */
7104 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7105 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7106 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7111 ERR("failed to convert param %d to %s from %s\n", i
,
7112 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7115 prgpvarg
[i
] = &rgvarg
[i
];
7119 prgpvarg
[i
] = src_arg
;
7122 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7123 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7124 && V_UNKNOWN(prgpvarg
[i
])) {
7125 IUnknown
*userdefined_iface
;
7128 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7132 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7134 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7138 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7139 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7142 else if (wParamFlags
& PARAMFLAG_FOPT
)
7145 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7146 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7148 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7154 VARIANTARG
*missing_arg
;
7155 /* if the function wants a pointer to a variant then
7156 * set that up, otherwise just pass the VT_ERROR in
7157 * the argument by value */
7158 if (rgvt
[i
] & VT_BYREF
)
7160 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7161 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7162 V_VARIANTREF(arg
) = missing_arg
;
7166 V_VT(missing_arg
) = VT_ERROR
;
7167 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7172 hres
= DISP_E_BADPARAMCOUNT
;
7176 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7178 /* VT_VOID is a special case for return types, so it is not
7179 * handled in the general function */
7180 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7181 V_VT(&varresult
) = VT_EMPTY
;
7184 V_VT(&varresult
) = 0;
7185 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7186 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7189 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7190 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7191 prgpvarg
, &varresult
);
7193 vargs_converted
= 0;
7195 for (i
= 0; i
< func_desc
->cParams
; i
++)
7197 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7198 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7200 if (wParamFlags
& PARAMFLAG_FLCID
)
7202 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7204 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7208 VariantInit(pVarResult
);
7209 /* deref return value */
7210 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7213 VARIANT_ClearInd(prgpvarg
[i
]);
7215 else if (vargs_converted
< pDispParams
->cArgs
)
7217 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7218 if (wParamFlags
& PARAMFLAG_FOUT
)
7220 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7222 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7226 ERR("failed to convert param %d to vt %d\n", i
,
7227 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7232 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7233 func_desc
->cParamsOpt
< 0 &&
7234 i
== func_desc
->cParams
-1)
7236 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7239 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7242 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7245 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7248 ERR("SafeArrayAccessData failed with %x\n", hres
);
7251 for (j
= 0; j
<= ubound
; j
++)
7252 VariantClear(&v
[j
]);
7253 hres
= SafeArrayUnaccessData(a
);
7256 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7260 VariantClear(&rgvarg
[i
]);
7263 else if (wParamFlags
& PARAMFLAG_FOPT
)
7265 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7266 VariantClear(&rgvarg
[i
]);
7269 VariantClear(&missing_arg
[i
]);
7272 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7274 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7275 hres
= DISP_E_EXCEPTION
;
7278 IErrorInfo
*pErrorInfo
;
7279 pExcepInfo
->scode
= V_ERROR(&varresult
);
7280 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7282 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7283 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7284 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7285 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7287 IErrorInfo_Release(pErrorInfo
);
7291 if (V_VT(&varresult
) != VT_ERROR
)
7293 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7297 VariantClear(pVarResult
);
7298 *pVarResult
= varresult
;
7301 VariantClear(&varresult
);
7304 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7305 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7306 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7307 (pDispParams
->cArgs
!= 0))
7309 if (V_VT(pVarResult
) == VT_DISPATCH
)
7311 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7312 /* Note: not VariantClear; we still need the dispatch
7313 * pointer to be valid */
7314 VariantInit(pVarResult
);
7315 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7316 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7317 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7318 IDispatch_Release(pDispatch
);
7322 VariantClear(pVarResult
);
7323 hres
= DISP_E_NOTACOLLECTION
;
7331 case FUNC_DISPATCH
: {
7334 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7335 if (SUCCEEDED(hres
)) {
7336 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7337 hres
= IDispatch_Invoke(
7338 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7339 pVarResult
,pExcepInfo
,pArgErr
7342 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7343 IDispatch_Release(disp
);
7345 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7349 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7354 TRACE("-- 0x%08x\n", hres
);
7357 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7360 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7361 if(FAILED(hres
)) return hres
;
7363 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7364 dump_VARDESC(var_desc
);
7365 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7369 /* not found, look for it in inherited interfaces */
7370 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7371 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7372 if(This
->impltypes
) {
7373 /* recursive search */
7375 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7376 if(SUCCEEDED(hres
)){
7377 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7378 ITypeInfo_Release(pTInfo
);
7381 WARN("Could not search inherited interface!\n");
7384 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7385 return DISP_E_MEMBERNOTFOUND
;
7388 /* ITypeInfo::GetDocumentation
7390 * Retrieves the documentation string, the complete Help file name and path,
7391 * and the context ID for the Help topic for a specified type description.
7393 * (Can be tested by the Visual Basic Editor in Word for instance.)
7395 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7396 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7397 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7399 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7400 const TLBFuncDesc
*pFDesc
;
7401 const TLBVarDesc
*pVDesc
;
7402 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7403 " HelpContext(%p) HelpFile(%p)\n",
7404 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7405 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7407 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7409 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7411 *pdwHelpContext
=This
->dwHelpContext
;
7413 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7415 }else {/* for a member */
7416 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7419 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7421 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7423 *pdwHelpContext
=pFDesc
->helpcontext
;
7425 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7428 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
7431 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7433 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7435 *pdwHelpContext
=pVDesc
->HelpContext
;
7437 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7442 if(This
->impltypes
&&
7443 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7444 /* recursive search */
7447 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7448 if(SUCCEEDED(result
)) {
7449 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7450 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7451 ITypeInfo_Release(pTInfo
);
7454 WARN("Could not search inherited interface!\n");
7457 WARN("member %d not found\n", memid
);
7458 return TYPE_E_ELEMENTNOTFOUND
;
7461 /* ITypeInfo::GetDllEntry
7463 * Retrieves a description or specification of an entry point for a function
7466 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7467 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7470 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7471 const TLBFuncDesc
*pFDesc
;
7473 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7475 if (pBstrDllName
) *pBstrDllName
= NULL
;
7476 if (pBstrName
) *pBstrName
= NULL
;
7477 if (pwOrdinal
) *pwOrdinal
= 0;
7479 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7480 return TYPE_E_BADMODULEKIND
;
7482 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7484 dump_TypeInfo(This
);
7486 dump_TLBFuncDescOne(pFDesc
);
7489 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7491 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7493 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7501 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7504 return TYPE_E_ELEMENTNOTFOUND
;
7507 /* internal function to make the inherited interfaces' methods appear
7508 * part of the interface */
7509 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7510 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7512 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7515 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7517 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7519 ITypeInfo
*pSubTypeInfo
;
7521 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7525 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7527 ITypeInfo_Release(pSubTypeInfo
);
7531 *hRefType
-= DISPATCH_HREF_OFFSET
;
7533 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7534 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7539 struct search_res_tlb_params
7545 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7547 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7548 static const WCHAR formatW
[] = {'\\','%','d',0};
7549 WCHAR szPath
[MAX_PATH
+1];
7550 ITypeLib
*pTLib
= NULL
;
7554 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7557 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7560 if (snprintfW(szPath
+ len
, sizeof(szPath
)/sizeof(WCHAR
) - len
, formatW
, LOWORD(lpszName
)) < 0)
7563 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7566 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7567 if (IsEqualGUID(params
->guid
, impl
->guid
))
7569 params
->pTLib
= pTLib
;
7570 return FALSE
; /* stop enumeration */
7572 ITypeLib_Release(pTLib
);
7578 /* ITypeInfo::GetRefTypeInfo
7580 * If a type description references other type descriptions, it retrieves
7581 * the referenced type descriptions.
7583 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7586 ITypeInfo
**ppTInfo
)
7588 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7589 HRESULT result
= E_FAIL
;
7592 return E_INVALIDARG
;
7594 if ((INT
)hRefType
< 0) {
7595 ITypeInfoImpl
*pTypeInfoImpl
;
7597 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7598 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7599 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7600 return TYPE_E_ELEMENTNOTFOUND
;
7602 /* when we meet a DUAL typeinfo, we must create the alternate
7605 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7607 *pTypeInfoImpl
= *This
;
7608 pTypeInfoImpl
->ref
= 0;
7609 list_init(&pTypeInfoImpl
->custdata_list
);
7611 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7612 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7614 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7616 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7617 /* the AddRef implicitly adds a reference to the parent typelib, which
7618 * stops the copied data from being destroyed until the new typeinfo's
7619 * refcount goes to zero, but we need to signal to the new instance to
7620 * not free its data structures when it is destroyed */
7621 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7623 ITypeInfo_AddRef(*ppTInfo
);
7626 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7627 (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7629 HREFTYPE href_dispatch
= hRefType
;
7630 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7632 TLBRefType
*ref_type
;
7633 ITypeLib
*pTLib
= NULL
;
7636 if(!(hRefType
& 0x1)){
7637 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7639 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7642 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7643 ITypeInfo_AddRef(*ppTInfo
);
7649 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7651 if(ref_type
->reference
== (hRefType
& (~0x3)))
7654 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7656 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7660 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7662 TRACE("internal reference\n");
7663 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7665 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7666 TRACE("typeinfo in imported typelib that is already loaded\n");
7667 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7668 ITypeLib_AddRef(pTLib
);
7671 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
7672 struct search_res_tlb_params params
;
7675 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7677 /* Search in resource table */
7678 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
7679 params
.pTLib
= NULL
;
7680 EnumResourceNamesW(NULL
, TYPELIBW
, search_res_tlb
, (LONG_PTR
)¶ms
);
7681 pTLib
= params
.pTLib
;
7686 /* Search on disk */
7687 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7688 ref_type
->pImpTLInfo
->wVersionMajor
,
7689 ref_type
->pImpTLInfo
->wVersionMinor
,
7690 This
->pTypeLib
->syskind
,
7691 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7693 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7695 result
= LoadTypeLib(libnam
, &pTLib
);
7696 SysFreeString(libnam
);
7699 if(SUCCEEDED(result
)) {
7700 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7701 ITypeLib_AddRef(pTLib
);
7705 if(SUCCEEDED(result
)) {
7706 if(ref_type
->index
== TLB_REF_USE_GUID
)
7707 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7709 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7712 ITypeLib_Release(pTLib
);
7716 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7717 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7721 /* ITypeInfo::AddressOfMember
7723 * Retrieves the addresses of static functions or variables, such as those
7726 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7727 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7729 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7735 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7737 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7741 module
= LoadLibraryW(dll
);
7744 ERR("couldn't load %s\n", debugstr_w(dll
));
7746 SysFreeString(entry
);
7747 return STG_E_FILENOTFOUND
;
7749 /* FIXME: store library somewhere where we can free it */
7754 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7755 entryA
= heap_alloc(len
);
7756 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7758 *ppv
= GetProcAddress(module
, entryA
);
7760 ERR("function not found %s\n", debugstr_a(entryA
));
7766 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7768 ERR("function not found %d\n", ordinal
);
7772 SysFreeString(entry
);
7775 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7780 /* ITypeInfo::CreateInstance
7782 * Creates a new instance of a type that describes a component object class
7785 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7786 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7788 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7792 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7798 WARN("Not able to aggregate\n");
7799 return CLASS_E_NOAGGREGATION
;
7802 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7803 if(FAILED(hr
)) return hr
;
7805 if(pTA
->typekind
!= TKIND_COCLASS
)
7807 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7813 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7816 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7817 TRACE("GetActiveObject rets %08x\n", hr
);
7820 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7821 IUnknown_Release(pUnk
);
7826 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7827 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7831 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7835 /* ITypeInfo::GetMops
7837 * Retrieves marshalling information.
7839 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7842 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7843 FIXME("(%p %d) stub!\n", This
, memid
);
7848 /* ITypeInfo::GetContainingTypeLib
7850 * Retrieves the containing type library and the index of the type description
7851 * within that type library.
7853 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7854 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7856 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7858 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7860 *pIndex
=This
->index
;
7861 TRACE("returning pIndex=%d\n", *pIndex
);
7865 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
7866 ITypeLib_AddRef(*ppTLib
);
7867 TRACE("returning ppTLib=%p\n", *ppTLib
);
7873 /* ITypeInfo::ReleaseTypeAttr
7875 * Releases a TYPEATTR previously returned by Get
7878 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7879 TYPEATTR
* pTypeAttr
)
7881 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7882 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7883 heap_free(pTypeAttr
);
7886 /* ITypeInfo::ReleaseFuncDesc
7888 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7890 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7892 FUNCDESC
*pFuncDesc
)
7894 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7897 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7899 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7900 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7901 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7903 SysFreeString((BSTR
)pFuncDesc
);
7906 /* ITypeInfo::ReleaseVarDesc
7908 * Releases a VARDESC previously returned by GetVarDesc.
7910 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7913 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7914 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7916 TLB_FreeVarDesc(pVarDesc
);
7919 /* ITypeInfo2::GetTypeKind
7921 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7924 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7925 TYPEKIND
*pTypeKind
)
7927 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7928 *pTypeKind
= This
->typeattr
.typekind
;
7929 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7933 /* ITypeInfo2::GetTypeFlags
7935 * Returns the type flags without any allocations. This returns a DWORD type
7936 * flag, which expands the type flags without growing the TYPEATTR (type
7940 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7942 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7943 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
7944 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7948 /* ITypeInfo2::GetFuncIndexOfMemId
7949 * Binds to a specific member based on a known DISPID, where the member name
7950 * is not known (for example, when binding to a default member).
7953 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7954 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7956 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7960 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7961 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7962 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7965 if(fdc
< This
->typeattr
.cFuncs
) {
7969 result
= TYPE_E_ELEMENTNOTFOUND
;
7971 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7972 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7976 /* TypeInfo2::GetVarIndexOfMemId
7978 * Binds to a specific member based on a known DISPID, where the member name
7979 * is not known (for example, when binding to a default member).
7982 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7983 MEMBERID memid
, UINT
*pVarIndex
)
7985 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7986 TLBVarDesc
*pVarInfo
;
7988 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7990 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
7992 return TYPE_E_ELEMENTNOTFOUND
;
7994 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7999 /* ITypeInfo2::GetCustData
8001 * Gets the custom data
8003 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8008 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8009 TLBCustData
*pCData
;
8011 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8013 if(!guid
|| !pVarVal
)
8014 return E_INVALIDARG
;
8016 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8018 VariantInit( pVarVal
);
8020 VariantCopy( pVarVal
, &pCData
->data
);
8022 VariantClear( pVarVal
);
8026 /* ITypeInfo2::GetFuncCustData
8028 * Gets the custom data
8030 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8036 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8037 TLBCustData
*pCData
;
8038 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8040 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8042 if(index
>= This
->typeattr
.cFuncs
)
8043 return TYPE_E_ELEMENTNOTFOUND
;
8045 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8047 return TYPE_E_ELEMENTNOTFOUND
;
8049 VariantInit(pVarVal
);
8050 VariantCopy(pVarVal
, &pCData
->data
);
8055 /* ITypeInfo2::GetParamCustData
8057 * Gets the custom data
8059 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8066 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8067 TLBCustData
*pCData
;
8068 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8070 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8071 debugstr_guid(guid
), pVarVal
);
8073 if(indexFunc
>= This
->typeattr
.cFuncs
)
8074 return TYPE_E_ELEMENTNOTFOUND
;
8076 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8077 return TYPE_E_ELEMENTNOTFOUND
;
8079 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8081 return TYPE_E_ELEMENTNOTFOUND
;
8083 VariantInit(pVarVal
);
8084 VariantCopy(pVarVal
, &pCData
->data
);
8089 /* ITypeInfo2::GetVarCustData
8091 * Gets the custom data
8093 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8099 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8100 TLBCustData
*pCData
;
8101 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8103 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8105 if(index
>= This
->typeattr
.cVars
)
8106 return TYPE_E_ELEMENTNOTFOUND
;
8108 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8110 return TYPE_E_ELEMENTNOTFOUND
;
8112 VariantInit(pVarVal
);
8113 VariantCopy(pVarVal
, &pCData
->data
);
8118 /* ITypeInfo2::GetImplCustData
8120 * Gets the custom data
8122 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8128 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8129 TLBCustData
*pCData
;
8130 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8132 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8134 if(index
>= This
->typeattr
.cImplTypes
)
8135 return TYPE_E_ELEMENTNOTFOUND
;
8137 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8139 return TYPE_E_ELEMENTNOTFOUND
;
8141 VariantInit(pVarVal
);
8142 VariantCopy(pVarVal
, &pCData
->data
);
8147 /* ITypeInfo2::GetDocumentation2
8149 * Retrieves the documentation string, the complete Help file name and path,
8150 * the localization context to use, and the context ID for the library Help
8151 * topic in the Help file.
8154 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8158 BSTR
*pbstrHelpString
,
8159 DWORD
*pdwHelpStringContext
,
8160 BSTR
*pbstrHelpStringDll
)
8162 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8163 const TLBFuncDesc
*pFDesc
;
8164 const TLBVarDesc
*pVDesc
;
8165 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8166 "HelpStringContext(%p) HelpStringDll(%p)\n",
8167 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8168 pbstrHelpStringDll
);
8169 /* the help string should be obtained from the helpstringdll,
8170 * using the _DLLGetDocumentation function, based on the supplied
8171 * lcid. Nice to do sometime...
8173 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8175 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8176 if(pdwHelpStringContext
)
8177 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8178 if(pbstrHelpStringDll
)
8179 *pbstrHelpStringDll
=
8180 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8182 }else {/* for a member */
8183 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
8186 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8187 if(pdwHelpStringContext
)
8188 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8189 if(pbstrHelpStringDll
)
8190 *pbstrHelpStringDll
=
8191 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8194 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
8197 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8198 if(pdwHelpStringContext
)
8199 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8200 if(pbstrHelpStringDll
)
8201 *pbstrHelpStringDll
=
8202 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8206 return TYPE_E_ELEMENTNOTFOUND
;
8209 /* ITypeInfo2::GetAllCustData
8211 * Gets all custom data items for the Type info.
8214 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8216 CUSTDATA
*pCustData
)
8218 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8220 TRACE("%p %p\n", This
, pCustData
);
8222 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8225 /* ITypeInfo2::GetAllFuncCustData
8227 * Gets all custom data items for the specified Function
8230 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8233 CUSTDATA
*pCustData
)
8235 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8236 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8238 TRACE("%p %u %p\n", This
, index
, pCustData
);
8240 if(index
>= This
->typeattr
.cFuncs
)
8241 return TYPE_E_ELEMENTNOTFOUND
;
8243 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8246 /* ITypeInfo2::GetAllParamCustData
8248 * Gets all custom data items for the Functions
8251 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8252 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8254 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8255 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8257 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8259 if(indexFunc
>= This
->typeattr
.cFuncs
)
8260 return TYPE_E_ELEMENTNOTFOUND
;
8262 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8263 return TYPE_E_ELEMENTNOTFOUND
;
8265 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8268 /* ITypeInfo2::GetAllVarCustData
8270 * Gets all custom data items for the specified Variable
8273 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8274 UINT index
, CUSTDATA
*pCustData
)
8276 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8277 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8279 TRACE("%p %u %p\n", This
, index
, pCustData
);
8281 if(index
>= This
->typeattr
.cVars
)
8282 return TYPE_E_ELEMENTNOTFOUND
;
8284 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8287 /* ITypeInfo2::GetAllImplCustData
8289 * Gets all custom data items for the specified implementation type
8292 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8295 CUSTDATA
*pCustData
)
8297 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8298 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8300 TRACE("%p %u %p\n", This
, index
, pCustData
);
8302 if(index
>= This
->typeattr
.cImplTypes
)
8303 return TYPE_E_ELEMENTNOTFOUND
;
8305 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8308 static const ITypeInfo2Vtbl tinfvt
=
8311 ITypeInfo_fnQueryInterface
,
8313 ITypeInfo_fnRelease
,
8315 ITypeInfo_fnGetTypeAttr
,
8316 ITypeInfo_fnGetTypeComp
,
8317 ITypeInfo_fnGetFuncDesc
,
8318 ITypeInfo_fnGetVarDesc
,
8319 ITypeInfo_fnGetNames
,
8320 ITypeInfo_fnGetRefTypeOfImplType
,
8321 ITypeInfo_fnGetImplTypeFlags
,
8322 ITypeInfo_fnGetIDsOfNames
,
8324 ITypeInfo_fnGetDocumentation
,
8325 ITypeInfo_fnGetDllEntry
,
8326 ITypeInfo_fnGetRefTypeInfo
,
8327 ITypeInfo_fnAddressOfMember
,
8328 ITypeInfo_fnCreateInstance
,
8329 ITypeInfo_fnGetMops
,
8330 ITypeInfo_fnGetContainingTypeLib
,
8331 ITypeInfo_fnReleaseTypeAttr
,
8332 ITypeInfo_fnReleaseFuncDesc
,
8333 ITypeInfo_fnReleaseVarDesc
,
8335 ITypeInfo2_fnGetTypeKind
,
8336 ITypeInfo2_fnGetTypeFlags
,
8337 ITypeInfo2_fnGetFuncIndexOfMemId
,
8338 ITypeInfo2_fnGetVarIndexOfMemId
,
8339 ITypeInfo2_fnGetCustData
,
8340 ITypeInfo2_fnGetFuncCustData
,
8341 ITypeInfo2_fnGetParamCustData
,
8342 ITypeInfo2_fnGetVarCustData
,
8343 ITypeInfo2_fnGetImplTypeCustData
,
8344 ITypeInfo2_fnGetDocumentation2
,
8345 ITypeInfo2_fnGetAllCustData
,
8346 ITypeInfo2_fnGetAllFuncCustData
,
8347 ITypeInfo2_fnGetAllParamCustData
,
8348 ITypeInfo2_fnGetAllVarCustData
,
8349 ITypeInfo2_fnGetAllImplTypeCustData
,
8352 /******************************************************************************
8353 * CreateDispTypeInfo [OLEAUT32.31]
8355 * Build type information for an object so it can be called through an
8356 * IDispatch interface.
8359 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8360 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8363 * This call allows an objects methods to be accessed through IDispatch, by
8364 * building an ITypeInfo object that IDispatch can use to call through.
8366 HRESULT WINAPI
CreateDispTypeInfo(
8367 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8368 LCID lcid
, /* [I] Locale Id */
8369 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8371 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8372 ITypeLibImpl
*pTypeLibImpl
;
8373 unsigned int param
, func
;
8374 TLBFuncDesc
*pFuncDesc
;
8378 pTypeLibImpl
= TypeLibImpl_Constructor();
8379 if (!pTypeLibImpl
) return E_FAIL
;
8381 pTypeLibImpl
->TypeInfoCount
= 2;
8382 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8384 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8385 pTIIface
->pTypeLib
= pTypeLibImpl
;
8386 pTIIface
->index
= 0;
8387 pTIIface
->Name
= NULL
;
8388 pTIIface
->dwHelpContext
= -1;
8389 pTIIface
->guid
= NULL
;
8390 pTIIface
->typeattr
.lcid
= lcid
;
8391 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8392 pTIIface
->typeattr
.wMajorVerNum
= 0;
8393 pTIIface
->typeattr
.wMinorVerNum
= 0;
8394 pTIIface
->typeattr
.cbAlignment
= 2;
8395 pTIIface
->typeattr
.cbSizeInstance
= -1;
8396 pTIIface
->typeattr
.cbSizeVft
= -1;
8397 pTIIface
->typeattr
.cFuncs
= 0;
8398 pTIIface
->typeattr
.cImplTypes
= 0;
8399 pTIIface
->typeattr
.cVars
= 0;
8400 pTIIface
->typeattr
.wTypeFlags
= 0;
8401 pTIIface
->hreftype
= 0;
8403 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8404 pFuncDesc
= pTIIface
->funcdescs
;
8405 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8406 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8407 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8408 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8409 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8410 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8411 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8412 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8413 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8414 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8415 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8416 pFuncDesc
->funcdesc
.cScodes
= 0;
8417 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8418 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8419 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8420 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8421 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8422 md
->cArgs
* sizeof(ELEMDESC
));
8423 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8424 for(param
= 0; param
< md
->cArgs
; param
++) {
8425 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8426 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8428 pFuncDesc
->helpcontext
= 0;
8429 pFuncDesc
->HelpStringContext
= 0;
8430 pFuncDesc
->HelpString
= NULL
;
8431 pFuncDesc
->Entry
= NULL
;
8432 list_init(&pFuncDesc
->custdata_list
);
8433 pTIIface
->typeattr
.cFuncs
++;
8437 dump_TypeInfo(pTIIface
);
8439 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8440 pTIClass
->pTypeLib
= pTypeLibImpl
;
8441 pTIClass
->index
= 1;
8442 pTIClass
->Name
= NULL
;
8443 pTIClass
->dwHelpContext
= -1;
8444 pTIClass
->guid
= NULL
;
8445 pTIClass
->typeattr
.lcid
= lcid
;
8446 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8447 pTIClass
->typeattr
.wMajorVerNum
= 0;
8448 pTIClass
->typeattr
.wMinorVerNum
= 0;
8449 pTIClass
->typeattr
.cbAlignment
= 2;
8450 pTIClass
->typeattr
.cbSizeInstance
= -1;
8451 pTIClass
->typeattr
.cbSizeVft
= -1;
8452 pTIClass
->typeattr
.cFuncs
= 0;
8453 pTIClass
->typeattr
.cImplTypes
= 1;
8454 pTIClass
->typeattr
.cVars
= 0;
8455 pTIClass
->typeattr
.wTypeFlags
= 0;
8456 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8458 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8460 ref
= heap_alloc_zero(sizeof(*ref
));
8461 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8462 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8464 dump_TypeInfo(pTIClass
);
8466 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8468 ITypeInfo_AddRef(*pptinfo
);
8469 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8475 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8477 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8479 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8482 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8484 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8486 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8489 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8491 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8493 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8496 static HRESULT WINAPI
ITypeComp_fnBind(
8501 ITypeInfo
** ppTInfo
,
8502 DESCKIND
* pDescKind
,
8505 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8506 const TLBFuncDesc
*pFDesc
;
8507 const TLBVarDesc
*pVDesc
;
8508 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8511 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8513 *pDescKind
= DESCKIND_NONE
;
8514 pBindPtr
->lpfuncdesc
= NULL
;
8517 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8518 pFDesc
= &This
->funcdescs
[fdc
];
8519 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8520 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8523 /* name found, but wrong flags */
8524 hr
= TYPE_E_TYPEMISMATCH
;
8528 if (fdc
< This
->typeattr
.cFuncs
)
8530 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8532 &pBindPtr
->lpfuncdesc
,
8533 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8536 *pDescKind
= DESCKIND_FUNCDESC
;
8537 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8538 ITypeInfo_AddRef(*ppTInfo
);
8541 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, szName
);
8543 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8546 *pDescKind
= DESCKIND_VARDESC
;
8547 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8548 ITypeInfo_AddRef(*ppTInfo
);
8553 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8554 /* recursive search */
8558 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8561 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8562 ITypeInfo_Release(pTInfo
);
8566 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8567 ITypeComp_Release(pTComp
);
8568 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8569 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8571 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8572 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8573 SysFreeString((BSTR
)tmp
);
8577 WARN("Could not search inherited interface!\n");
8579 if (hr
== DISP_E_MEMBERNOTFOUND
)
8581 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8585 static HRESULT WINAPI
ITypeComp_fnBindType(
8589 ITypeInfo
** ppTInfo
,
8590 ITypeComp
** ppTComp
)
8592 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8594 /* strange behaviour (does nothing) but like the
8597 if (!ppTInfo
|| !ppTComp
)
8606 static const ITypeCompVtbl tcompvt
=
8609 ITypeComp_fnQueryInterface
,
8611 ITypeComp_fnRelease
,
8614 ITypeComp_fnBindType
8617 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8618 ICreateTypeLib2
** ppctlib
)
8623 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8625 if (!szFile
) return E_INVALIDARG
;
8627 This
= TypeLibImpl_Constructor();
8629 return E_OUTOFMEMORY
;
8631 This
->lcid
= GetSystemDefaultLCID();
8632 This
->syskind
= syskind
;
8633 This
->ptr_size
= get_ptr_size(syskind
);
8635 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8637 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8638 return E_OUTOFMEMORY
;
8640 lstrcpyW(This
->path
, szFile
);
8642 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8643 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8647 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8648 REFIID riid
, void **object
)
8650 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8652 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8655 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8657 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8659 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8662 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8664 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8666 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8669 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8670 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8672 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8673 ITypeInfoImpl
*info
;
8676 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8678 if (!ctinfo
|| !name
)
8679 return E_INVALIDARG
;
8681 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8683 return TYPE_E_NAMECONFLICT
;
8685 if (This
->typeinfos
)
8686 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8687 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8689 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8691 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8693 info
->pTypeLib
= This
;
8694 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8695 info
->index
= This
->TypeInfoCount
;
8696 info
->typeattr
.typekind
= kind
;
8697 info
->typeattr
.cbAlignment
= 4;
8699 switch (info
->typeattr
.typekind
) {
8701 case TKIND_INTERFACE
:
8702 case TKIND_DISPATCH
:
8704 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
8708 info
->typeattr
.cbSizeInstance
= 0;
8711 info
->typeattr
.cbSizeInstance
= 2;
8714 info
->typeattr
.cbSizeInstance
= -0x75;
8717 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
8718 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
8722 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8723 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8725 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8729 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8731 ++This
->TypeInfoCount
;
8736 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8739 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8741 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8744 return E_INVALIDARG
;
8746 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8751 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8752 WORD majorVerNum
, WORD minorVerNum
)
8754 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8756 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8758 This
->ver_major
= majorVerNum
;
8759 This
->ver_minor
= minorVerNum
;
8764 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8767 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8769 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8771 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8776 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8779 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8781 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8784 return E_INVALIDARG
;
8786 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8791 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8792 LPOLESTR helpFileName
)
8794 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8796 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8799 return E_INVALIDARG
;
8801 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8806 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8809 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8811 TRACE("%p %d\n", This
, helpContext
);
8813 This
->dwHelpContext
= helpContext
;
8818 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8821 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8823 TRACE("%p %x\n", This
, lcid
);
8825 This
->set_lcid
= lcid
;
8830 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8833 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8835 TRACE("%p %x\n", This
, libFlags
);
8837 This
->libflags
= libFlags
;
8842 typedef struct tagWMSFT_SegContents
{
8845 } WMSFT_SegContents
;
8847 typedef struct tagWMSFT_TLBFile
{
8849 WMSFT_SegContents typeinfo_seg
;
8850 WMSFT_SegContents impfile_seg
;
8851 WMSFT_SegContents impinfo_seg
;
8852 WMSFT_SegContents ref_seg
;
8853 WMSFT_SegContents guidhash_seg
;
8854 WMSFT_SegContents guid_seg
;
8855 WMSFT_SegContents namehash_seg
;
8856 WMSFT_SegContents name_seg
;
8857 WMSFT_SegContents string_seg
;
8858 WMSFT_SegContents typdesc_seg
;
8859 WMSFT_SegContents arraydesc_seg
;
8860 WMSFT_SegContents custdata_seg
;
8861 WMSFT_SegContents cdguids_seg
;
8863 WMSFT_SegContents aux_seg
;
8866 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8867 WMSFT_TLBFile
*file
)
8873 file
->string_seg
.len
= 0;
8874 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8877 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8879 return E_UNEXPECTED
;
8881 size
+= sizeof(INT16
);
8883 size
= (size
+ 4) & ~0x3;
8887 file
->string_seg
.len
+= size
;
8889 /* temporarily use str->offset to store the length of the aligned,
8890 * converted string */
8894 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8897 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8900 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8901 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8903 heap_free(file
->string_seg
.data
);
8904 return E_UNEXPECTED
;
8907 *((INT16
*)data
) = size
;
8909 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8913 str
->offset
= last_offs
;
8920 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8921 WMSFT_TLBFile
*file
)
8926 MSFT_NameIntro
*last_intro
= NULL
;
8928 file
->header
.nametablecount
= 0;
8929 file
->header
.nametablechars
= 0;
8931 file
->name_seg
.len
= 0;
8932 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8935 size
= strlenW(str
->str
);
8936 file
->header
.nametablechars
+= size
;
8937 file
->header
.nametablecount
++;
8939 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8941 return E_UNEXPECTED
;
8943 size
+= sizeof(MSFT_NameIntro
);
8945 size
= (size
+ 4) & ~0x3;
8949 file
->name_seg
.len
+= size
;
8951 /* temporarily use str->offset to store the length of the aligned,
8952 * converted string */
8956 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8957 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
8960 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8962 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8964 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8965 data
+ sizeof(MSFT_NameIntro
),
8966 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8968 heap_free(file
->name_seg
.data
);
8969 return E_UNEXPECTED
;
8971 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
8973 intro
->hreftype
= -1; /* TODO? */
8974 intro
->namelen
= size
& 0xFF;
8975 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8976 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
8977 intro
->namelen
|= hash
<< 16;
8978 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
8979 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
8981 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
8982 str
->offset
- size
- sizeof(MSFT_NameIntro
));
8984 /* update str->offset to actual value to use in other
8985 * compilation functions that require positions within
8986 * the string table */
8990 str
->offset
= last_offs
;
8995 last_intro
->hreftype
= 0; /* last one is 0? */
9000 static inline int hash_guid(GUID
*guid
)
9004 for (i
= 0; i
< 8; i
++)
9005 hash
^= ((const short *)guid
)[i
];
9010 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9013 MSFT_GuidEntry
*entry
;
9015 int hash_key
, *guidhashtab
;
9017 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9018 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9020 entry
= file
->guid_seg
.data
;
9022 guidhashtab
= file
->guidhash_seg
.data
;
9023 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9024 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9025 entry
->hreftype
= guid
->hreftype
;
9027 hash_key
= hash_guid(&guid
->guid
);
9028 entry
->next_hash
= guidhashtab
[hash_key
];
9029 guidhashtab
[hash_key
] = offs
;
9031 guid
->offset
= offs
;
9032 offs
+= sizeof(MSFT_GuidEntry
);
9039 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9042 VARTYPE arg_type
= V_VT(value
);
9045 DWORD ret
= file
->custdata_seg
.len
;
9047 if(arg_type
== VT_INT
)
9049 if(arg_type
== VT_UINT
)
9053 if(V_VT(value
) != arg_type
) {
9054 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9056 ERR("VariantChangeType failed: %08x\n", hres
);
9061 /* Check if default value can be stored in-place */
9066 if(V_UI4(&v
) > 0x3ffffff)
9079 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9082 /* have to allocate space in custdata_seg */
9091 /* Construct the data to be allocated */
9094 if(file
->custdata_seg
.data
){
9095 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9096 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9097 file
->custdata_seg
.len
+= sizeof(int) * 2;
9099 file
->custdata_seg
.len
= sizeof(int) * 2;
9100 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9103 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9104 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9106 /* TODO: Check if the encoded data is already present in custdata_seg */
9112 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9115 if(file
->custdata_seg
.data
){
9116 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9117 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9118 file
->custdata_seg
.len
+= len
;
9120 file
->custdata_seg
.len
= len
;
9121 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9124 *((unsigned short *)data
) = V_VT(value
);
9125 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9126 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9127 if(V_BSTR(&v
)[i
] <= 0x7f)
9128 data
[i
+6] = V_BSTR(&v
)[i
];
9132 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9133 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9136 /* TODO: Check if the encoded data is already present in custdata_seg */
9141 FIXME("Argument type not yet handled\n");
9146 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9148 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9150 DWORD offs
= file
->arraydesc_seg
.len
;
9154 /* TODO: we should check for duplicates, but that's harder because each
9155 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9156 * at the library-level) */
9158 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9159 if(!file
->arraydesc_seg
.data
)
9160 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9162 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9163 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9165 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9166 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9167 for(i
= 0; i
< desc
->cDims
; ++i
){
9168 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9169 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9175 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9181 VARTYPE vt
, subtype
;
9192 vt
= desc
->vt
& VT_TYPEMASK
;
9194 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9196 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9197 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9199 *out_size
+= 2 * sizeof(DWORD
);
9200 }else if(vt
== VT_CARRAY
){
9201 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9202 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9204 }else if(vt
== VT_USERDEFINED
){
9205 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9206 encoded
[1] = desc
->u
.hreftype
;
9207 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9209 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9227 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9230 data
= file
->typdesc_seg
.data
;
9231 while(offs
< file
->typdesc_seg
.len
){
9232 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9234 offs
+= sizeof(encoded
);
9237 file
->typdesc_seg
.len
+= sizeof(encoded
);
9238 if(!file
->typdesc_seg
.data
)
9239 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9241 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9243 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9248 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9250 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9251 DWORD ret
= cdguids_seg
->len
, offs
;
9252 MSFT_CDGuid
*cdguid
;
9255 if(list_empty(custdata_list
))
9258 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9259 if(!cdguids_seg
->data
){
9260 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9262 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9263 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9266 offs
= ret
+ sizeof(MSFT_CDGuid
);
9267 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9268 cdguid
->GuidOffset
= cd
->guid
->offset
;
9269 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9270 cdguid
->next
= offs
;
9271 offs
+= sizeof(MSFT_CDGuid
);
9281 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9282 WMSFT_TLBFile
*file
)
9284 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9285 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9286 MSFT_VarRecord
*varrecord
;
9287 MSFT_FuncRecord
*funcrecord
;
9289 DWORD
*name
, *offsets
, offs
;
9291 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9292 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9294 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9296 /* optional fields */
9297 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9298 if(!list_empty(&desc
->custdata_list
))
9299 recorded_size
+= 7 * sizeof(INT
);
9300 else if(desc
->HelpStringContext
!= 0)
9301 recorded_size
+= 6 * sizeof(INT
);
9303 else if(desc
->Entry
)
9304 recorded_size
+= 3 * sizeof(INT
);
9305 else if(desc
->HelpString
)
9306 recorded_size
+= 2 * sizeof(INT
);
9307 else if(desc
->helpcontext
)
9308 recorded_size
+= sizeof(INT
);
9310 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9312 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9313 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9314 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9319 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9322 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9323 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9325 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9327 /* optional fields */
9328 if(desc
->HelpStringContext
!= 0)
9329 recorded_size
+= 5 * sizeof(INT
);
9330 else if(!list_empty(&desc
->custdata_list
))
9331 recorded_size
+= 4 * sizeof(INT
);
9333 else if(desc
->HelpString
)
9334 recorded_size
+= 2 * sizeof(INT
);
9335 else if(desc
->HelpContext
!= 0)
9336 recorded_size
+= sizeof(INT
);
9338 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9341 if(!recorded_size
&& !extra_size
)
9344 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9346 aux_seg
->len
+= recorded_size
+ extra_size
;
9348 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9351 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9353 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9355 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9357 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9360 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9361 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9362 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9363 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9365 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9366 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9367 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9368 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9371 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9376 * ^has_param_defaults
9377 * ^oEntry_is_intresource
9379 funcrecord
->FKCCIC
=
9380 desc
->funcdesc
.funckind
|
9381 (desc
->funcdesc
.invkind
<< 3) |
9382 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9383 (desc
->funcdesc
.callconv
<< 8);
9385 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9386 funcrecord
->FKCCIC
|= 0x2000;
9388 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9389 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9390 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9391 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9394 if(paramdefault_size
> 0)
9395 funcrecord
->FKCCIC
|= 0x1000;
9397 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9398 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9400 /* optional fields */
9402 if(!list_empty(&desc
->custdata_list
)){
9403 size
+= 7 * sizeof(INT
);
9404 funcrecord
->HelpContext
= desc
->helpcontext
;
9405 if(desc
->HelpString
)
9406 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9408 funcrecord
->oHelpString
= -1;
9410 funcrecord
->oEntry
= -1;
9411 else if(IS_INTRESOURCE(desc
->Entry
))
9412 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9414 funcrecord
->oEntry
= desc
->Entry
->offset
;
9415 funcrecord
->res9
= -1;
9416 funcrecord
->resA
= -1;
9417 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9418 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9419 }else if(desc
->HelpStringContext
!= 0){
9420 size
+= 6 * sizeof(INT
);
9421 funcrecord
->HelpContext
= desc
->helpcontext
;
9422 if(desc
->HelpString
)
9423 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9425 funcrecord
->oHelpString
= -1;
9427 funcrecord
->oEntry
= -1;
9428 else if(IS_INTRESOURCE(desc
->Entry
))
9429 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9431 funcrecord
->oEntry
= desc
->Entry
->offset
;
9432 funcrecord
->res9
= -1;
9433 funcrecord
->resA
= -1;
9434 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9435 }else if(desc
->Entry
){
9436 size
+= 3 * sizeof(INT
);
9437 funcrecord
->HelpContext
= desc
->helpcontext
;
9438 if(desc
->HelpString
)
9439 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9441 funcrecord
->oHelpString
= -1;
9443 funcrecord
->oEntry
= -1;
9444 else if(IS_INTRESOURCE(desc
->Entry
))
9445 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9447 funcrecord
->oEntry
= desc
->Entry
->offset
;
9448 }else if(desc
->HelpString
){
9449 size
+= 2 * sizeof(INT
);
9450 funcrecord
->HelpContext
= desc
->helpcontext
;
9451 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9452 }else if(desc
->helpcontext
){
9453 size
+= sizeof(INT
);
9454 funcrecord
->HelpContext
= desc
->helpcontext
;
9457 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9458 size
+= paramdefault_size
;
9460 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9461 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9463 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9464 if(desc
->pParamDesc
[j
].Name
)
9465 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9468 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9470 if(paramdefault_size
){
9471 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9472 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9473 else if(paramdefault_size
)
9478 size
+= sizeof(MSFT_ParameterInfo
);
9481 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9487 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9490 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9491 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9492 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9493 DWORD size
= 5 * sizeof(INT
);
9495 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9496 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9497 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9498 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9500 if(desc
->vardesc
.varkind
== VAR_CONST
){
9501 varrecord
->vardescsize
+= sizeof(VARIANT
);
9502 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9504 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9507 if(desc
->HelpStringContext
!= 0){
9508 size
+= 5 * sizeof(INT
);
9509 varrecord
->HelpContext
= desc
->HelpContext
;
9510 if(desc
->HelpString
)
9511 varrecord
->HelpString
= desc
->HelpString
->offset
;
9513 varrecord
->HelpString
= -1;
9514 varrecord
->res9
= -1;
9515 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9516 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9517 }else if(!list_empty(&desc
->custdata_list
)){
9518 size
+= 4 * sizeof(INT
);
9519 varrecord
->HelpContext
= desc
->HelpContext
;
9520 if(desc
->HelpString
)
9521 varrecord
->HelpString
= desc
->HelpString
->offset
;
9523 varrecord
->HelpString
= -1;
9524 varrecord
->res9
= -1;
9525 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9526 }else if(desc
->HelpString
){
9527 size
+= 2 * sizeof(INT
);
9528 varrecord
->HelpContext
= desc
->HelpContext
;
9529 if(desc
->HelpString
)
9530 varrecord
->HelpString
= desc
->HelpString
->offset
;
9532 varrecord
->HelpString
= -1;
9533 }else if(desc
->HelpContext
!= 0){
9534 size
+= sizeof(INT
);
9535 varrecord
->HelpContext
= desc
->HelpContext
;
9538 varrecord
->Info
= size
| (i
<< 16);
9544 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9547 memid
= (MEMBERID
*)varrecord
;
9548 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9549 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9550 *memid
= desc
->funcdesc
.memid
;
9553 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9554 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9555 *memid
= desc
->vardesc
.memid
;
9559 name
= (UINT
*)memid
;
9560 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9561 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9563 *name
= desc
->Name
->offset
;
9568 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9569 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9571 *name
= desc
->Name
->offset
;
9580 typedef struct tagWMSFT_RefChunk
{
9587 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9589 DWORD offs
= file
->ref_seg
.len
, i
;
9590 WMSFT_RefChunk
*chunk
;
9592 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9593 if(!file
->ref_seg
.data
)
9594 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9596 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9598 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9600 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9601 chunk
->href
= info
->impltypes
[i
].hRef
;
9602 chunk
->res04
= info
->impltypes
[i
].implflags
;
9604 if(i
< info
->typeattr
.cImplTypes
- 1)
9605 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9614 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9618 size
= sizeof(MSFT_TypeInfoBase
);
9621 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9622 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9623 base
->typekind
= TKIND_DISPATCH
;
9625 base
->typekind
= info
->typeattr
.typekind
;
9626 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9627 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
9628 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9633 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
9639 base
->posguid
= info
->guid
->offset
;
9642 base
->flags
= info
->typeattr
.wTypeFlags
;
9644 base
->NameOffset
= info
->Name
->offset
;
9646 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9647 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9649 base
->NameOffset
= -1;
9651 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
9653 base
->docstringoffs
= info
->DocString
->offset
;
9655 base
->docstringoffs
= -1;
9656 base
->helpstringcontext
= info
->dwHelpStringContext
;
9657 base
->helpcontext
= info
->dwHelpContext
;
9658 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9659 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
9660 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
9661 base
->size
= info
->typeattr
.cbSizeInstance
;
9662 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
9663 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9664 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
9665 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9666 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
9668 base
->datatype1
= info
->DllName
->offset
;
9670 base
->datatype1
= -1;
9672 if(info
->typeattr
.cImplTypes
> 0)
9673 base
->datatype1
= info
->impltypes
[0].hRef
;
9675 base
->datatype1
= -1;
9677 base
->datatype2
= index
; /* FIXME: i think there's more here */
9685 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9689 file
->typeinfo_seg
.len
= 0;
9690 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9691 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9692 *junk
= file
->typeinfo_seg
.len
;
9694 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9697 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9698 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9700 file
->aux_seg
.len
= 0;
9701 file
->aux_seg
.data
= NULL
;
9703 file
->typeinfo_seg
.len
= 0;
9704 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9705 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9706 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9707 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9711 typedef struct tagWMSFT_ImpFile
{
9717 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9720 WMSFT_ImpFile
*impfile
;
9722 DWORD last_offs
= 0;
9724 file
->impfile_seg
.len
= 0;
9725 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9729 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9733 path
= implib
->name
;
9734 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9736 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9739 size
+= sizeof(INT16
);
9741 size
= (size
+ 4) & ~0x3;
9745 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9748 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9750 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9751 int strlen
= 0, size
;
9753 impfile
= (WMSFT_ImpFile
*)data
;
9754 impfile
->guid_offs
= implib
->guid
->offset
;
9755 impfile
->lcid
= implib
->lcid
;
9756 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9758 data
+= sizeof(WMSFT_ImpFile
);
9761 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9765 path
= implib
->name
;
9766 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9767 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9769 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9772 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9774 size
= strlen
+ sizeof(INT16
);
9776 size
= (size
+ 4) & ~0x3;
9779 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9782 implib
->offset
= last_offs
;
9783 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9787 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9790 TLBRefType
*ref_type
;
9793 WMSFT_compile_impfile(This
, file
);
9795 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9796 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9798 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9799 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9800 if(ref_type
->index
== TLB_REF_USE_GUID
){
9801 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9802 info
->oGuid
= ref_type
->guid
->offset
;
9804 info
->oGuid
= ref_type
->index
;
9805 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9811 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9813 file
->guidhash_seg
.len
= 0x80;
9814 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9815 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9818 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9820 file
->namehash_seg
.len
= 0x200;
9821 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9822 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9825 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9827 if(contents
&& contents
->len
){
9828 segdir
->offset
= *running_offset
;
9829 segdir
->length
= contents
->len
;
9830 *running_offset
+= segdir
->length
;
9832 segdir
->offset
= -1;
9836 /* TODO: do these ever change? */
9838 segdir
->res0c
= 0xf;
9841 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9845 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9848 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9852 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9854 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9855 base
->memoffset
+= file_len
;
9862 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9864 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9865 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9866 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9867 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9868 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9869 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9870 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9871 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9872 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9873 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9874 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9875 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9876 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9877 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9880 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9882 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9884 DWORD written
, junk_size
, junk_offs
, running_offset
;
9891 TRACE("%p\n", This
);
9893 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
9894 if(This
->typeinfos
[i
]->needs_layout
)
9895 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
9897 memset(&file
, 0, sizeof(file
));
9899 file
.header
.magic1
= 0x5446534D;
9900 file
.header
.magic2
= 0x00010002;
9901 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9902 file
.header
.lcid2
= This
->set_lcid
;
9903 file
.header
.varflags
= 0x40 | This
->syskind
;
9905 file
.header
.varflags
|= 0x10;
9906 if (This
->HelpStringDll
)
9907 file
.header
.varflags
|= HELPDLLFLAG
;
9908 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
9909 file
.header
.flags
= This
->libflags
;
9910 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9911 file
.header
.helpcontext
= This
->dwHelpContext
;
9912 file
.header
.res44
= 0x20;
9913 file
.header
.res48
= 0x80;
9914 file
.header
.dispatchpos
= This
->dispatch_href
;
9916 WMSFT_compile_namehash(This
, &file
);
9917 /* do name and string compilation to get offsets for other compilations */
9918 hres
= WMSFT_compile_names(This
, &file
);
9920 WMSFT_free_file(&file
);
9924 hres
= WMSFT_compile_strings(This
, &file
);
9926 WMSFT_free_file(&file
);
9930 WMSFT_compile_guidhash(This
, &file
);
9931 hres
= WMSFT_compile_guids(This
, &file
);
9933 WMSFT_free_file(&file
);
9938 file
.header
.helpfile
= This
->HelpFile
->offset
;
9940 file
.header
.helpfile
= -1;
9943 file
.header
.helpstring
= This
->DocString
->offset
;
9945 file
.header
.helpstring
= -1;
9947 /* do some more segment compilation */
9948 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9949 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9952 file
.header
.NameOffset
= This
->Name
->offset
;
9954 file
.header
.NameOffset
= -1;
9956 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
9959 file
.header
.posguid
= This
->guid
->offset
;
9961 file
.header
.posguid
= -1;
9963 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9964 if(file
.header
.varflags
& HELPDLLFLAG
)
9965 junk_size
+= sizeof(DWORD
);
9967 junk
= heap_alloc_zero(junk_size
);
9968 if(file
.header
.varflags
& HELPDLLFLAG
){
9969 *junk
= This
->HelpStringDll
->offset
;
9978 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
9979 WMSFT_compile_impinfo(This
, &file
);
9983 TRACE("header at: 0x%x\n", running_offset
);
9984 running_offset
+= sizeof(file
.header
);
9986 TRACE("junk at: 0x%x\n", running_offset
);
9987 running_offset
+= junk_size
;
9989 TRACE("segdir at: 0x%x\n", running_offset
);
9990 running_offset
+= sizeof(file
.segdir
);
9992 TRACE("typeinfo at: 0x%x\n", running_offset
);
9993 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
9995 TRACE("guidhashtab at: 0x%x\n", running_offset
);
9996 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
9998 TRACE("guidtab at: 0x%x\n", running_offset
);
9999 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10001 TRACE("reftab at: 0x%x\n", running_offset
);
10002 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10004 TRACE("impinfo at: 0x%x\n", running_offset
);
10005 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10007 TRACE("impfiles at: 0x%x\n", running_offset
);
10008 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10010 TRACE("namehashtab at: 0x%x\n", running_offset
);
10011 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10013 TRACE("nametab at: 0x%x\n", running_offset
);
10014 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10016 TRACE("stringtab at: 0x%x\n", running_offset
);
10017 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10019 TRACE("typdesc at: 0x%x\n", running_offset
);
10020 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10022 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10023 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10025 TRACE("custdata at: 0x%x\n", running_offset
);
10026 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10028 TRACE("cdguids at: 0x%x\n", running_offset
);
10029 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10031 TRACE("res0e at: 0x%x\n", running_offset
);
10032 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10034 TRACE("res0f at: 0x%x\n", running_offset
);
10035 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10037 TRACE("aux_seg at: 0x%x\n", running_offset
);
10039 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10041 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10042 FILE_ATTRIBUTE_NORMAL
, 0);
10043 if (outfile
== INVALID_HANDLE_VALUE
){
10044 WMSFT_free_file(&file
);
10046 return TYPE_E_IOERROR
;
10049 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10051 WMSFT_free_file(&file
);
10052 CloseHandle(outfile
);
10054 return TYPE_E_IOERROR
;
10057 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10060 WMSFT_free_file(&file
);
10061 CloseHandle(outfile
);
10062 return TYPE_E_IOERROR
;
10065 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10067 WMSFT_free_file(&file
);
10068 CloseHandle(outfile
);
10069 return TYPE_E_IOERROR
;
10072 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10073 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10074 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10075 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10076 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10077 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10078 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10079 WMSFT_write_segment(outfile
, &file
.name_seg
);
10080 WMSFT_write_segment(outfile
, &file
.string_seg
);
10081 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10082 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10083 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10084 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10085 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10087 WMSFT_free_file(&file
);
10089 CloseHandle(outfile
);
10094 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10097 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10098 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10102 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10103 REFGUID guid
, VARIANT
*varVal
)
10105 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10108 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10110 if (!guid
|| !varVal
)
10111 return E_INVALIDARG
;
10113 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10115 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10118 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10119 ULONG helpStringContext
)
10121 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10122 FIXME("%p %u - stub\n", This
, helpStringContext
);
10126 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10129 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10130 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10133 return E_INVALIDARG
;
10135 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10140 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10141 ICreateTypeLib2_fnQueryInterface
,
10142 ICreateTypeLib2_fnAddRef
,
10143 ICreateTypeLib2_fnRelease
,
10144 ICreateTypeLib2_fnCreateTypeInfo
,
10145 ICreateTypeLib2_fnSetName
,
10146 ICreateTypeLib2_fnSetVersion
,
10147 ICreateTypeLib2_fnSetGuid
,
10148 ICreateTypeLib2_fnSetDocString
,
10149 ICreateTypeLib2_fnSetHelpFileName
,
10150 ICreateTypeLib2_fnSetHelpContext
,
10151 ICreateTypeLib2_fnSetLcid
,
10152 ICreateTypeLib2_fnSetLibFlags
,
10153 ICreateTypeLib2_fnSaveAllChanges
,
10154 ICreateTypeLib2_fnDeleteTypeInfo
,
10155 ICreateTypeLib2_fnSetCustData
,
10156 ICreateTypeLib2_fnSetHelpStringContext
,
10157 ICreateTypeLib2_fnSetHelpStringDll
10160 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10161 REFIID riid
, void **object
)
10163 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10165 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10168 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10170 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10172 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10175 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10177 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10179 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10182 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10185 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10187 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10189 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10194 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10197 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10201 TRACE("%p %x\n", This
, typeFlags
);
10203 if (typeFlags
& TYPEFLAG_FDUAL
) {
10204 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10206 ITypeInfo
*dispatch
;
10210 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10214 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10215 ITypeLib_Release(stdole
);
10219 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10220 ITypeInfo_Release(dispatch
);
10225 old_flags
= This
->typeattr
.wTypeFlags
;
10226 This
->typeattr
.wTypeFlags
= typeFlags
;
10228 hres
= ICreateTypeInfo2_LayOut(iface
);
10229 if (FAILED(hres
)) {
10230 This
->typeattr
.wTypeFlags
= old_flags
;
10237 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10240 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10242 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10245 return E_INVALIDARG
;
10247 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10252 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10255 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10257 TRACE("%p %d\n", This
, helpContext
);
10259 This
->dwHelpContext
= helpContext
;
10264 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10265 WORD majorVerNum
, WORD minorVerNum
)
10267 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10269 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10271 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10272 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10277 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10278 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10280 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10282 ITypeLib
*container
;
10283 TLBRefType
*ref_type
;
10285 TYPEATTR
*typeattr
;
10289 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10291 if (!typeInfo
|| !refType
)
10292 return E_INVALIDARG
;
10294 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10298 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10299 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10301 ITypeLib_Release(container
);
10303 *refType
= target
->hreftype
;
10308 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10309 if (FAILED(hres
)) {
10310 ITypeLib_Release(container
);
10314 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10315 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10316 implib
->lcid
== libattr
->lcid
&&
10317 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10318 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10322 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10323 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10325 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10326 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10327 implib
->name
= SysAllocString(our_container
->path
);
10329 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10330 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10332 implib
->name
= NULL
;
10333 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10337 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10338 implib
->lcid
= libattr
->lcid
;
10339 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10340 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10342 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10345 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10346 ITypeLib_Release(container
);
10348 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10353 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10354 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10355 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10356 ref_type
->tkind
== typeattr
->typekind
)
10361 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10362 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10364 ref_type
->tkind
= typeattr
->typekind
;
10365 ref_type
->pImpTLInfo
= implib
;
10366 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10368 ref_type
->index
= TLB_REF_USE_GUID
;
10370 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10372 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10375 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10377 *refType
= ref_type
->reference
| 0x1;
10379 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10380 This
->pTypeLib
->dispatch_href
= *refType
;
10385 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10386 UINT index
, FUNCDESC
*funcDesc
)
10388 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10389 TLBFuncDesc tmp_func_desc
, *func_desc
;
10394 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10396 if (!funcDesc
|| funcDesc
->oVft
& 3)
10397 return E_INVALIDARG
;
10399 switch (This
->typeattr
.typekind
) {
10401 if (funcDesc
->funckind
!= FUNC_STATIC
)
10402 return TYPE_E_BADMODULEKIND
;
10404 case TKIND_DISPATCH
:
10405 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10406 return TYPE_E_BADMODULEKIND
;
10409 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10410 return TYPE_E_BADMODULEKIND
;
10413 if (index
> This
->typeattr
.cFuncs
)
10414 return TYPE_E_ELEMENTNOTFOUND
;
10416 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10417 !funcDesc
->cParams
)
10418 return TYPE_E_INCONSISTENTPROPFUNCS
;
10421 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10422 funcDesc
->oVft
% 8 != 0)
10423 return E_INVALIDARG
;
10426 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10427 TLBFuncDesc_Constructor(&tmp_func_desc
);
10429 tmp_func_desc
.funcdesc
= *funcDesc
;
10431 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10432 tmp_func_desc
.funcdesc
.oVft
|= 1;
10434 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10435 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10436 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10438 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10439 tmp_func_desc
.funcdesc
.cScodes
= 0;
10442 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10443 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10444 buf_size
+= sizeof(ELEMDESC
);
10445 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10447 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10448 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10450 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10451 if (FAILED(hres
)) {
10452 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10453 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10457 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10458 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10459 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10460 if (FAILED(hres
)) {
10461 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10462 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10465 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10466 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10467 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10468 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10469 if (FAILED(hres
)) {
10470 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10471 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10477 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10479 if (This
->funcdescs
) {
10480 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10481 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10483 if (index
< This
->typeattr
.cFuncs
) {
10484 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10485 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10486 func_desc
= This
->funcdescs
+ index
;
10488 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10490 /* move custdata lists to the new memory location */
10491 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10493 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10494 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10495 list_init(&fd
->custdata_list
);
10497 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10498 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10503 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10505 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10506 list_init(&func_desc
->custdata_list
);
10508 ++This
->typeattr
.cFuncs
;
10510 This
->needs_layout
= TRUE
;
10515 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10516 UINT index
, HREFTYPE refType
)
10518 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10519 TLBImplType
*impl_type
;
10522 TRACE("%p %u %d\n", This
, index
, refType
);
10524 switch(This
->typeattr
.typekind
){
10525 case TKIND_COCLASS
: {
10527 FIXME("Unhandled index: -1\n");
10531 if(index
!= This
->typeattr
.cImplTypes
)
10532 return TYPE_E_ELEMENTNOTFOUND
;
10536 case TKIND_INTERFACE
:
10537 case TKIND_DISPATCH
:
10538 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10539 return TYPE_E_ELEMENTNOTFOUND
;
10542 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10546 if (This
->impltypes
){
10549 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10550 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10552 if (index
< This
->typeattr
.cImplTypes
) {
10553 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10554 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10555 impl_type
= This
->impltypes
+ index
;
10557 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10559 /* move custdata lists to the new memory location */
10560 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10562 TLBImplType
*it
= &This
->impltypes
[i
];
10563 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10564 list_init(&it
->custdata_list
);
10566 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10567 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10572 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10574 memset(impl_type
, 0, sizeof(TLBImplType
));
10575 TLBImplType_Constructor(impl_type
);
10576 impl_type
->hRef
= refType
;
10578 ++This
->typeattr
.cImplTypes
;
10580 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10581 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10583 hres
= ICreateTypeInfo2_LayOut(iface
);
10590 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10591 UINT index
, INT implTypeFlags
)
10593 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10594 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10596 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10598 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10599 return TYPE_E_BADMODULEKIND
;
10601 if (index
>= This
->typeattr
.cImplTypes
)
10602 return TYPE_E_ELEMENTNOTFOUND
;
10604 impl_type
->implflags
= implTypeFlags
;
10609 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10612 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10614 TRACE("%p %d\n", This
, alignment
);
10616 This
->typeattr
.cbAlignment
= alignment
;
10621 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10624 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10626 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10629 return E_INVALIDARG
;
10631 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10633 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10638 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10639 UINT index
, VARDESC
*varDesc
)
10641 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10642 TLBVarDesc
*var_desc
;
10644 TRACE("%p %u %p\n", This
, index
, varDesc
);
10646 if (This
->vardescs
){
10649 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10650 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
10652 if (index
< This
->typeattr
.cVars
) {
10653 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10654 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
10655 var_desc
= This
->vardescs
+ index
;
10657 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
10659 /* move custdata lists to the new memory location */
10660 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
10662 TLBVarDesc
*var
= &This
->vardescs
[i
];
10663 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10664 list_init(&var
->custdata_list
);
10666 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10667 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10672 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10674 TLBVarDesc_Constructor(var_desc
);
10675 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10676 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10678 ++This
->typeattr
.cVars
;
10680 This
->needs_layout
= TRUE
;
10685 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10686 UINT index
, LPOLESTR
*names
, UINT numNames
)
10688 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10689 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10692 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10695 return E_INVALIDARG
;
10697 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
10698 return TYPE_E_ELEMENTNOTFOUND
;
10700 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10701 if(numNames
> func_desc
->funcdesc
.cParams
)
10702 return TYPE_E_ELEMENTNOTFOUND
;
10704 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10705 return TYPE_E_ELEMENTNOTFOUND
;
10707 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
10708 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10709 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10710 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10711 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10712 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10714 return TYPE_E_AMBIGUOUSNAME
;
10718 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10720 for (i
= 1; i
< numNames
; ++i
) {
10721 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10722 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10728 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10729 UINT index
, LPOLESTR name
)
10731 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10733 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10736 return E_INVALIDARG
;
10738 if(index
>= This
->typeattr
.cVars
)
10739 return TYPE_E_ELEMENTNOTFOUND
;
10741 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10745 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10746 TYPEDESC
*tdescAlias
)
10748 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10751 TRACE("%p %p\n", This
, tdescAlias
);
10754 return E_INVALIDARG
;
10756 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
10757 return TYPE_E_BADMODULEKIND
;
10759 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
10763 heap_free(This
->tdescAlias
);
10764 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10765 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10770 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10771 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10773 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10774 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10778 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10779 UINT index
, LPOLESTR docString
)
10781 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10782 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10784 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10787 return E_INVALIDARG
;
10789 if(index
>= This
->typeattr
.cFuncs
)
10790 return TYPE_E_ELEMENTNOTFOUND
;
10792 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10797 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10798 UINT index
, LPOLESTR docString
)
10800 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10801 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10803 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10806 return E_INVALIDARG
;
10808 if(index
>= This
->typeattr
.cVars
)
10809 return TYPE_E_ELEMENTNOTFOUND
;
10811 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10816 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10817 UINT index
, DWORD helpContext
)
10819 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10820 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10822 TRACE("%p %u %d\n", This
, index
, helpContext
);
10824 if(index
>= This
->typeattr
.cFuncs
)
10825 return TYPE_E_ELEMENTNOTFOUND
;
10827 func_desc
->helpcontext
= helpContext
;
10832 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10833 UINT index
, DWORD helpContext
)
10835 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10836 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10838 TRACE("%p %u %d\n", This
, index
, helpContext
);
10840 if(index
>= This
->typeattr
.cVars
)
10841 return TYPE_E_ELEMENTNOTFOUND
;
10843 var_desc
->HelpContext
= helpContext
;
10848 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10849 UINT index
, BSTR bstrMops
)
10851 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10852 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10856 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10859 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10861 TRACE("%p %p\n", This
, idlDesc
);
10864 return E_INVALIDARG
;
10866 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
10867 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10872 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10874 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10876 TLBFuncDesc
*func_desc
;
10877 UINT user_vft
= 0, i
, depth
= 0;
10878 HRESULT hres
= S_OK
;
10880 TRACE("%p\n", This
);
10882 This
->needs_layout
= FALSE
;
10884 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10888 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
10893 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10895 if (SUCCEEDED(hres
)) {
10896 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10898 if (SUCCEEDED(hres
)) {
10899 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10900 if (FAILED(hres
)) {
10901 ITypeInfo_Release(inh
);
10902 ITypeInfo_Release(tinfo
);
10905 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
10906 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10910 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10911 if(SUCCEEDED(hres
)){
10913 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10914 if(SUCCEEDED(hres
)){
10915 ITypeInfo_Release(inh
);
10919 }while(SUCCEEDED(hres
));
10922 ITypeInfo_Release(inh
);
10923 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10924 This
->typeattr
.cbSizeVft
= 0;
10927 ITypeInfo_Release(tinfo
);
10930 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10931 This
->typeattr
.cbSizeVft
= 0;
10934 ITypeInfo_Release(tinfo
);
10937 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
10938 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10940 This
->typeattr
.cbSizeVft
= 0;
10942 func_desc
= This
->funcdescs
;
10944 while (i
< This
->typeattr
.cFuncs
) {
10945 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10946 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
10948 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10949 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10951 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
10953 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10956 BOOL reset
= FALSE
;
10958 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10960 iter
= This
->funcdescs
;
10961 while (j
< This
->typeattr
.cFuncs
) {
10962 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10964 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
10967 ++func_desc
->funcdesc
.memid
;
10968 iter
= This
->funcdescs
;
10981 if (user_vft
> This
->typeattr
.cbSizeVft
)
10982 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
10984 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
10985 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
10986 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
10988 BOOL reset
= FALSE
;
10991 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
10993 iter
= This
->vardescs
;
10994 while (j
< This
->typeattr
.cVars
) {
10995 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
10997 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11000 ++var_desc
->vardesc
.memid
;
11001 iter
= This
->vardescs
;
11011 ITypeInfo_Release(tinfo
);
11015 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11018 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11019 FIXME("%p %u - stub\n", This
, index
);
11023 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11024 MEMBERID memid
, INVOKEKIND invKind
)
11026 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11027 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11031 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11034 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11035 FIXME("%p %u - stub\n", This
, index
);
11039 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11042 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11043 FIXME("%p %x - stub\n", This
, memid
);
11047 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11050 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11051 FIXME("%p %u - stub\n", This
, index
);
11055 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11056 REFGUID guid
, VARIANT
*varVal
)
11060 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11062 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11064 if (!guid
|| !varVal
)
11065 return E_INVALIDARG
;
11067 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11069 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11072 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11073 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11075 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11076 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11080 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11081 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11083 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11084 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11088 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(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_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11097 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11099 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11100 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11104 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11105 ULONG helpStringContext
)
11107 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11109 TRACE("%p %u\n", This
, helpStringContext
);
11111 This
->dwHelpStringContext
= helpStringContext
;
11116 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11117 UINT index
, ULONG helpStringContext
)
11119 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11120 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11124 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11125 UINT index
, ULONG helpStringContext
)
11127 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11128 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11132 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11134 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11135 FIXME("%p - stub\n", This
);
11139 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11142 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11144 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11147 return E_INVALIDARG
;
11149 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11154 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11155 ICreateTypeInfo2_fnQueryInterface
,
11156 ICreateTypeInfo2_fnAddRef
,
11157 ICreateTypeInfo2_fnRelease
,
11158 ICreateTypeInfo2_fnSetGuid
,
11159 ICreateTypeInfo2_fnSetTypeFlags
,
11160 ICreateTypeInfo2_fnSetDocString
,
11161 ICreateTypeInfo2_fnSetHelpContext
,
11162 ICreateTypeInfo2_fnSetVersion
,
11163 ICreateTypeInfo2_fnAddRefTypeInfo
,
11164 ICreateTypeInfo2_fnAddFuncDesc
,
11165 ICreateTypeInfo2_fnAddImplType
,
11166 ICreateTypeInfo2_fnSetImplTypeFlags
,
11167 ICreateTypeInfo2_fnSetAlignment
,
11168 ICreateTypeInfo2_fnSetSchema
,
11169 ICreateTypeInfo2_fnAddVarDesc
,
11170 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11171 ICreateTypeInfo2_fnSetVarName
,
11172 ICreateTypeInfo2_fnSetTypeDescAlias
,
11173 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11174 ICreateTypeInfo2_fnSetFuncDocString
,
11175 ICreateTypeInfo2_fnSetVarDocString
,
11176 ICreateTypeInfo2_fnSetFuncHelpContext
,
11177 ICreateTypeInfo2_fnSetVarHelpContext
,
11178 ICreateTypeInfo2_fnSetMops
,
11179 ICreateTypeInfo2_fnSetTypeIdldesc
,
11180 ICreateTypeInfo2_fnLayOut
,
11181 ICreateTypeInfo2_fnDeleteFuncDesc
,
11182 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11183 ICreateTypeInfo2_fnDeleteVarDesc
,
11184 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11185 ICreateTypeInfo2_fnDeleteImplType
,
11186 ICreateTypeInfo2_fnSetCustData
,
11187 ICreateTypeInfo2_fnSetFuncCustData
,
11188 ICreateTypeInfo2_fnSetParamCustData
,
11189 ICreateTypeInfo2_fnSetVarCustData
,
11190 ICreateTypeInfo2_fnSetImplTypeCustData
,
11191 ICreateTypeInfo2_fnSetHelpStringContext
,
11192 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11193 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11194 ICreateTypeInfo2_fnInvalidate
,
11195 ICreateTypeInfo2_fnSetName
11198 /******************************************************************************
11199 * ClearCustData (OLEAUT32.171)
11201 * Clear a custom data type's data.
11204 * lpCust [I] The custom data type instance
11209 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11211 if (lpCust
&& lpCust
->cCustData
)
11213 if (lpCust
->prgCustData
)
11217 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11218 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11220 CoTaskMemFree(lpCust
->prgCustData
);
11221 lpCust
->prgCustData
= NULL
;
11223 lpCust
->cCustData
= 0;