4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
46 * -. lousy fatal error handling
51 #include "wine/port.h"
60 #define NONAMELESSUNION
71 #include "wine/unicode.h"
74 #include "wine/debug.h"
76 #include "wine/list.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
79 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
93 WORD type_id
; /* Type identifier */
94 WORD count
; /* Number of resources of this type */
95 DWORD resloader
; /* SetResourceHandler() */
101 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
102 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
103 static void TLB_FreeVarDesc(VARDESC
*);
105 /****************************************************************************
108 * Takes p_iVal (which is in little endian) and returns it
109 * in the host machine's byte order.
111 #ifdef WORDS_BIGENDIAN
112 static WORD
FromLEWord(WORD p_iVal
)
114 return (((p_iVal
& 0x00FF) << 8) |
115 ((p_iVal
& 0xFF00) >> 8));
119 static DWORD
FromLEDWord(DWORD p_iVal
)
121 return (((p_iVal
& 0x000000FF) << 24) |
122 ((p_iVal
& 0x0000FF00) << 8) |
123 ((p_iVal
& 0x00FF0000) >> 8) |
124 ((p_iVal
& 0xFF000000) >> 24));
127 #define FromLEWord(X) (X)
128 #define FromLEDWord(X) (X)
131 #define DISPATCH_HREF_OFFSET 0x01000000
132 #define DISPATCH_HREF_MASK 0xff000000
134 /****************************************************************************
137 * Fix byte order in any structure if necessary
139 #ifdef WORDS_BIGENDIAN
140 static void FromLEWords(void *p_Val
, int p_iSize
)
144 p_iSize
/= sizeof(WORD
);
147 *Val
= FromLEWord(*Val
);
154 static void FromLEDWords(void *p_Val
, int p_iSize
)
158 p_iSize
/= sizeof(DWORD
);
161 *Val
= FromLEDWord(*Val
);
167 #define FromLEWords(X,Y) /*nothing*/
168 #define FromLEDWords(X,Y) /*nothing*/
172 * Find a typelib key which matches a requested maj.min version.
174 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
176 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
180 INT best_maj
= -1, best_min
= -1;
183 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
184 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
186 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
189 len
= sizeof(key_name
);
191 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
195 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
197 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
199 if (*wMaj
== 0xffff && *wMin
== 0xffff)
201 if (v_maj
> best_maj
) best_maj
= v_maj
;
202 if (v_min
> best_min
) best_min
= v_min
;
204 else if (*wMaj
== v_maj
)
211 break; /* exact match */
213 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
216 len
= sizeof(key_name
);
220 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
222 if (*wMaj
== 0xffff && *wMin
== 0xffff)
224 if (best_maj
>= 0 && best_min
>= 0)
232 if (*wMaj
== best_maj
&& best_min
>= 0)
240 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
241 /* buffer must be at least 60 characters long */
242 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
244 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
245 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
247 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
248 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
249 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
253 /* get the path of an interface key, in the form "Interface\\<guid>" */
254 /* buffer must be at least 50 characters long */
255 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
257 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
259 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
260 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
264 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
265 /* buffer must be at least 16 characters long */
266 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
268 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
269 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
270 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
271 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
273 sprintfW( buffer
, LcidFormatW
, lcid
);
276 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
277 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
278 case SYS_WIN64
: strcatW( buffer
, win64W
); break;
280 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
286 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
288 struct tlibredirect_data
302 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
303 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
304 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
306 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
310 WCHAR Path
[MAX_PATH
];
313 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
317 ACTCTX_SECTION_KEYED_DATA data
;
319 data
.cbSize
= sizeof(data
);
320 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
322 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
326 if (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
)
327 return TYPE_E_LIBNOTREGISTERED
;
329 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
330 len
= SearchPathW( NULL
, nameW
, NULL
, sizeof(Path
)/sizeof(WCHAR
), Path
, NULL
);
331 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
333 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
334 *path
= SysAllocString( Path
);
339 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
340 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
342 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
343 if (res
== ERROR_FILE_NOT_FOUND
)
345 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
346 return TYPE_E_LIBNOTREGISTERED
;
348 else if (res
!= ERROR_SUCCESS
)
350 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
351 return TYPE_E_REGISTRYACCESS
;
356 LONG dwPathLen
= sizeof(Path
);
358 get_lcid_subkey( myLCID
, syskind
, buffer
);
360 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
364 else if (myLCID
== lcid
)
366 /* try with sub-langid */
367 myLCID
= SUBLANGID(lcid
);
369 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
371 /* try with system langid */
381 *path
= SysAllocString( Path
);
386 TRACE_(typelib
)("-- 0x%08x\n", hr
);
390 /****************************************************************************
391 * QueryPathOfRegTypeLib [OLEAUT32.164]
393 * Gets the path to a registered type library.
396 * guid [I] referenced guid
397 * wMaj [I] major version
398 * wMin [I] minor version
400 * path [O] path of typelib
404 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
405 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
408 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
412 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
417 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
420 /******************************************************************************
421 * CreateTypeLib [OLEAUT32.160] creates a typelib
427 HRESULT WINAPI
CreateTypeLib(
428 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
430 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
434 /******************************************************************************
435 * LoadTypeLib [OLEAUT32.161]
437 * Loads a type library
440 * szFile [I] Name of file to load from.
441 * pptLib [O] Pointer that receives ITypeLib object on success.
448 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
450 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
452 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
453 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
456 /******************************************************************************
457 * LoadTypeLibEx [OLEAUT32.183]
459 * Loads and optionally registers a type library
465 HRESULT WINAPI
LoadTypeLibEx(
466 LPCOLESTR szFile
, /* [in] Name of file to load from */
467 REGKIND regkind
, /* [in] Specify kind of registration */
468 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
470 WCHAR szPath
[MAX_PATH
+1];
473 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
477 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
482 case REGKIND_DEFAULT
:
483 /* don't register typelibs supplied with full path. Experimentation confirms the following */
484 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
485 (szFile
[0] && (szFile
[1] == ':'))) break;
486 /* else fall-through */
488 case REGKIND_REGISTER
:
489 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
491 ITypeLib_Release(*pptLib
);
499 TRACE(" returns %08x\n",res
);
503 /******************************************************************************
504 * LoadRegTypeLib [OLEAUT32.162]
506 * Loads a registered type library.
509 * rguid [I] GUID of the registered type library.
510 * wVerMajor [I] major version.
511 * wVerMinor [I] minor version.
512 * lcid [I] locale ID.
513 * ppTLib [O] pointer that receives an ITypeLib object on success.
517 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
520 HRESULT WINAPI
LoadRegTypeLib(
532 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
536 res
= LoadTypeLib(bstr
, ppTLib
);
543 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
546 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
547 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
551 ITypeLib_Release(*ppTLib
);
553 res
= TYPE_E_LIBNOTREGISTERED
;
559 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
565 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
566 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
567 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
568 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
569 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
570 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
572 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
577 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
578 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
579 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
581 get_interface_key( &tattr
->guid
, keyName
);
582 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
583 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
586 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
587 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
589 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
590 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
591 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
592 (const BYTE
*)PSOA
, sizeof PSOA
);
596 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
597 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
598 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
599 (const BYTE
*)PSOA
, sizeof PSOA
);
603 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
604 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
607 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
608 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
610 StringFromGUID2(&libattr
->guid
, buffer
, 40);
611 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
612 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
613 sprintfW(buffer
, fmtver
, libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
614 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
615 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
623 /******************************************************************************
624 * RegisterTypeLib [OLEAUT32.163]
625 * Adds information about a type library to the System Registry
627 * Docs: ITypeLib FAR * ptlib
628 * Docs: OLECHAR FAR* szFullPath
629 * Docs: OLECHAR FAR* szHelpDir
635 HRESULT WINAPI
RegisterTypeLib(
636 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
637 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
638 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
650 if (ptlib
== NULL
|| szFullPath
== NULL
)
653 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
657 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
660 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
663 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
664 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
668 /* Set the human-readable name of the typelib */
669 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
673 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
674 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
680 /* Make up the name of the typelib path subkey */
681 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
683 /* Create the typelib path subkey */
684 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
685 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
687 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
688 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
696 /* Create the flags subkey */
697 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
698 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
700 /* FIXME: is %u correct? */
701 static const WCHAR formatW
[] = {'%','u',0};
703 sprintfW(buf
, formatW
, attr
->wLibFlags
);
704 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
705 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
713 /* create the helpdir subkey */
714 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
715 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
717 BOOL freeHelpDir
= FALSE
;
720 /* if we created a new key, and helpDir was null, set the helpdir
721 to the directory which contains the typelib. However,
722 if we just opened an existing key, we leave the helpdir alone */
723 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
724 szHelpDir
= SysAllocString(szFullPath
);
725 pIndexStr
= strrchrW(szHelpDir
, '\\');
732 /* if we have an szHelpDir, set it! */
733 if (szHelpDir
!= NULL
) {
734 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
735 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
741 if (freeHelpDir
) SysFreeString(szHelpDir
);
753 /* register OLE Automation-compatible interfaces for this typelib */
754 types
= ITypeLib_GetTypeInfoCount(ptlib
);
755 for (tidx
=0; tidx
<types
; tidx
++) {
756 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
757 LPOLESTR name
= NULL
;
758 ITypeInfo
*tinfo
= NULL
;
760 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
763 case TKIND_INTERFACE
:
764 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
765 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
769 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
770 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
774 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
779 TYPEATTR
*tattr
= NULL
;
780 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
783 TRACE_(typelib
)("guid=%s, flags=%04x (",
784 debugstr_guid(&tattr
->guid
),
787 if (TRACE_ON(typelib
)) {
788 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
808 /* Register all dispinterfaces (which includes dual interfaces) and
809 oleautomation interfaces */
810 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
811 kind
== TKIND_DISPATCH
)
814 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
816 /* register interface<->typelib coupling */
817 TLB_register_interface(attr
, name
, tattr
, 0);
819 /* register TLBs into the opposite registry view, too */
820 if(opposite
== KEY_WOW64_32KEY
||
821 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
822 TLB_register_interface(attr
, name
, tattr
, opposite
);
825 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
828 ITypeInfo_Release(tinfo
);
835 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
840 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
842 WCHAR subKeyName
[50];
845 /* the path to the type */
846 get_interface_key( guid
, subKeyName
);
848 /* Delete its bits */
849 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
852 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
853 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
854 RegDeleteKeyW(subKey
, TypeLibW
);
856 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
859 /******************************************************************************
860 * UnRegisterTypeLib [OLEAUT32.186]
861 * Removes information about a type library from the System Registry
868 HRESULT WINAPI
UnRegisterTypeLib(
869 REFGUID libid
, /* [in] Guid of the library */
870 WORD wVerMajor
, /* [in] major version */
871 WORD wVerMinor
, /* [in] minor version */
872 LCID lcid
, /* [in] locale id */
875 BSTR tlibPath
= NULL
;
878 WCHAR subKeyName
[50];
881 BOOL deleteOtherStuff
;
883 TYPEATTR
* typeAttr
= NULL
;
885 ITypeInfo
* typeInfo
= NULL
;
886 ITypeLib
* typeLib
= NULL
;
889 TRACE("(IID: %s)\n",debugstr_guid(libid
));
891 /* Create the path to the key */
892 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
894 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
896 TRACE("Unsupported syskind %i\n", syskind
);
897 result
= E_INVALIDARG
;
901 /* get the path to the typelib on disk */
902 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
903 result
= E_INVALIDARG
;
907 /* Try and open the key to the type library. */
908 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
909 result
= E_INVALIDARG
;
913 /* Try and load the type library */
914 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
915 result
= TYPE_E_INVALIDSTATE
;
919 /* remove any types registered with this typelib */
920 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
921 for (i
=0; i
<numTypes
; i
++) {
922 /* get the kind of type */
923 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
927 /* skip non-interfaces, and get type info for the type */
928 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
931 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
934 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
938 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
939 kind
== TKIND_DISPATCH
)
942 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
944 TLB_unregister_interface(&typeAttr
->guid
, 0);
946 /* unregister TLBs into the opposite registry view, too */
947 if(opposite
== KEY_WOW64_32KEY
||
948 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
949 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
954 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
956 if (typeInfo
) ITypeInfo_Release(typeInfo
);
960 /* Now, delete the type library path subkey */
961 get_lcid_subkey( lcid
, syskind
, subKeyName
);
962 RegDeleteKeyW(key
, subKeyName
);
963 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
964 RegDeleteKeyW(key
, subKeyName
);
966 /* check if there is anything besides the FLAGS/HELPDIR keys.
967 If there is, we don't delete them */
968 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
969 deleteOtherStuff
= TRUE
;
971 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
972 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
974 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
975 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
976 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
977 deleteOtherStuff
= FALSE
;
981 /* only delete the other parts of the key if we're absolutely sure */
982 if (deleteOtherStuff
) {
983 RegDeleteKeyW(key
, FLAGSW
);
984 RegDeleteKeyW(key
, HELPDIRW
);
988 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
989 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
990 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
994 SysFreeString(tlibPath
);
995 if (typeLib
) ITypeLib_Release(typeLib
);
996 if (key
) RegCloseKey(key
);
1000 /******************************************************************************
1001 * RegisterTypeLibForUser [OLEAUT32.442]
1002 * Adds information about a type library to the user registry
1004 * Docs: ITypeLib FAR * ptlib
1005 * Docs: OLECHAR FAR* szFullPath
1006 * Docs: OLECHAR FAR* szHelpDir
1012 HRESULT WINAPI
RegisterTypeLibForUser(
1013 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
1014 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
1015 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1018 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1019 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1020 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1023 /******************************************************************************
1024 * UnRegisterTypeLibForUser [OLEAUT32.443]
1025 * Removes information about a type library from the user registry
1031 HRESULT WINAPI
UnRegisterTypeLibForUser(
1032 REFGUID libid
, /* [in] GUID of the library */
1033 WORD wVerMajor
, /* [in] major version */
1034 WORD wVerMinor
, /* [in] minor version */
1035 LCID lcid
, /* [in] locale id */
1038 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1039 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1040 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1043 /*======================= ITypeLib implementation =======================*/
1045 typedef struct tagTLBGuid
{
1052 typedef struct tagTLBCustData
1059 /* data structure for import typelibs */
1060 typedef struct tagTLBImpLib
1062 int offset
; /* offset in the file (MSFT)
1063 offset in nametable (SLTG)
1064 just used to identify library while reading
1066 TLBGuid
*guid
; /* libid */
1067 BSTR name
; /* name */
1069 LCID lcid
; /* lcid of imported typelib */
1071 WORD wVersionMajor
; /* major version number */
1072 WORD wVersionMinor
; /* minor version number */
1074 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1075 NULL if not yet loaded */
1079 typedef struct tagTLBString
{
1085 /* internal ITypeLib data */
1086 typedef struct tagITypeLibImpl
1088 ITypeLib2 ITypeLib2_iface
;
1089 ITypeComp ITypeComp_iface
;
1090 ICreateTypeLib2 ICreateTypeLib2_iface
;
1101 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1102 * exported to the application as a UNICODE string.
1104 struct list string_list
;
1105 struct list name_list
;
1106 struct list guid_list
;
1108 const TLBString
*Name
;
1109 const TLBString
*DocString
;
1110 const TLBString
*HelpFile
;
1111 const TLBString
*HelpStringDll
;
1112 DWORD dwHelpContext
;
1113 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1114 struct tagITypeInfoImpl
**typeinfos
;
1115 struct list custdata_list
;
1116 struct list implib_list
;
1117 int ctTypeDesc
; /* number of items in type desc array */
1118 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1119 library. Only used while reading MSFT
1121 struct list ref_list
; /* list of ref types in this typelib */
1122 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1125 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1131 static const ITypeLib2Vtbl tlbvt
;
1132 static const ITypeCompVtbl tlbtcvt
;
1133 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1135 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1137 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1140 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1142 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1145 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1147 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1150 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1152 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1155 /* ITypeLib methods */
1156 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1157 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1159 /*======================= ITypeInfo implementation =======================*/
1161 /* data for referenced types */
1162 typedef struct tagTLBRefType
1164 INT index
; /* Type index for internal ref or for external ref
1165 it the format is SLTG. -2 indicates to
1169 TLBGuid
*guid
; /* guid of the referenced type */
1170 /* if index == TLB_REF_USE_GUID */
1172 HREFTYPE reference
; /* The href of this ref */
1173 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1174 TLB_REF_INTERNAL for internal refs
1175 TLB_REF_NOT_FOUND for broken refs */
1180 #define TLB_REF_USE_GUID -2
1182 #define TLB_REF_INTERNAL (void*)-2
1183 #define TLB_REF_NOT_FOUND (void*)-1
1185 /* internal Parameter data */
1186 typedef struct tagTLBParDesc
1188 const TLBString
*Name
;
1189 struct list custdata_list
;
1192 /* internal Function data */
1193 typedef struct tagTLBFuncDesc
1195 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1196 const TLBString
*Name
; /* the name of this function */
1197 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1199 int HelpStringContext
;
1200 const TLBString
*HelpString
;
1201 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1202 struct list custdata_list
;
1205 /* internal Variable data */
1206 typedef struct tagTLBVarDesc
1208 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1209 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1210 const TLBString
*Name
; /* the name of this variable */
1212 int HelpStringContext
;
1213 const TLBString
*HelpString
;
1214 struct list custdata_list
;
1217 /* internal implemented interface data */
1218 typedef struct tagTLBImplType
1220 HREFTYPE hRef
; /* hRef of interface */
1221 int implflags
; /* IMPLFLAG_*s */
1222 struct list custdata_list
;
1225 /* internal TypeInfo data */
1226 typedef struct tagITypeInfoImpl
1228 ITypeInfo2 ITypeInfo2_iface
;
1229 ITypeComp ITypeComp_iface
;
1230 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1232 BOOL not_attached_to_typelib
;
1237 MEMBERID memidConstructor
;
1238 MEMBERID memidDestructor
;
1239 LPOLESTR lpstrSchema
;
1240 ULONG cbSizeInstance
;
1250 TYPEDESC
*tdescAlias
;
1251 IDLDESC idldescType
;
1253 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1254 int index
; /* index in this typelib; */
1255 HREFTYPE hreftype
; /* hreftype for app object binding */
1256 /* type libs seem to store the doc strings in ascii
1257 * so why should we do it in unicode?
1259 const TLBString
*Name
;
1260 const TLBString
*DocString
;
1261 const TLBString
*DllName
;
1262 const TLBString
*Schema
;
1263 DWORD dwHelpContext
;
1264 DWORD dwHelpStringContext
;
1267 TLBFuncDesc
*funcdescs
;
1270 TLBVarDesc
*vardescs
;
1272 /* Implemented Interfaces */
1273 TLBImplType
*impltypes
;
1275 struct list
*pcustdata_list
;
1276 struct list custdata_list
;
1279 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1281 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1284 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1286 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1289 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1291 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1294 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1296 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1299 static const ITypeInfo2Vtbl tinfvt
;
1300 static const ITypeCompVtbl tcompvt
;
1301 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1303 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1304 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1306 typedef struct tagTLBContext
1308 unsigned int oStart
; /* start of TLB in file */
1309 unsigned int pos
; /* current pos */
1310 unsigned int length
; /* total length */
1311 void *mapping
; /* memory mapping */
1312 MSFT_SegDir
* pTblDir
;
1313 ITypeLibImpl
* pLibInfo
;
1317 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1319 return str
!= NULL
? str
->str
: NULL
;
1322 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1326 return memcmp(left
, str
->str
, len
);
1329 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1331 return guid
!= NULL
? &guid
->guid
: NULL
;
1334 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1336 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1339 static int get_ptr_size(SYSKIND syskind
)
1349 WARN("Unhandled syskind: 0x%x\n", syskind
);
1356 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1357 if (pTD
->vt
& VT_RESERVED
)
1358 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1359 if (pTD
->vt
& VT_BYREF
)
1360 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1361 if (pTD
->vt
& VT_ARRAY
)
1362 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1363 if (pTD
->vt
& VT_VECTOR
)
1364 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1365 switch(pTD
->vt
& VT_TYPEMASK
) {
1366 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1367 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1368 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1369 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1370 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1371 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1372 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1373 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1374 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1375 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1376 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1377 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1378 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1379 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1380 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1381 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1382 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1383 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1384 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1385 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1386 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1387 pTD
->u
.hreftype
); break;
1388 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1389 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1390 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1391 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1393 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1394 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1396 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1397 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1398 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1401 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1405 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1407 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1408 dump_TypeDesc(&edesc
->tdesc
,buf
);
1409 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1410 MESSAGE("\t\tu.paramdesc.wParamFlags");
1411 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1412 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1413 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1414 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1415 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1416 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1417 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1418 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1419 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1421 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1423 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1424 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1425 MESSAGE("Param %d:\n",i
);
1426 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1428 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1429 switch (funcdesc
->funckind
) {
1430 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1431 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1432 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1433 case FUNC_STATIC
: MESSAGE("static");break;
1434 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1435 default: MESSAGE("unknown");break;
1437 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1438 switch (funcdesc
->invkind
) {
1439 case INVOKE_FUNC
: MESSAGE("func");break;
1440 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1441 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1442 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1444 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1445 switch (funcdesc
->callconv
) {
1446 case CC_CDECL
: MESSAGE("cdecl");break;
1447 case CC_PASCAL
: MESSAGE("pascal");break;
1448 case CC_STDCALL
: MESSAGE("stdcall");break;
1449 case CC_SYSCALL
: MESSAGE("syscall");break;
1452 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1453 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1454 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1456 MESSAGE("\telemdescFunc (return value type):\n");
1457 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1460 static const char * const typekind_desc
[] =
1473 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1476 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1477 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1478 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1481 dump_FUNCDESC(&(pfd
->funcdesc
));
1483 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1484 if(pfd
->Entry
== NULL
)
1485 MESSAGE("\tentry: (null)\n");
1486 else if(pfd
->Entry
== (void*)-1)
1487 MESSAGE("\tentry: invalid\n");
1488 else if(IS_INTRESOURCE(pfd
->Entry
))
1489 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1491 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1493 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1497 dump_TLBFuncDescOne(pfd
);
1502 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1506 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1512 static void dump_TLBImpLib(const TLBImpLib
*import
)
1514 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1515 debugstr_w(import
->name
));
1516 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1517 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1520 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1524 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1526 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1527 if(ref
->index
== -1)
1528 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1530 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1532 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1534 TRACE_(typelib
)("in lib\n");
1535 dump_TLBImpLib(ref
->pImpTLInfo
);
1540 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1545 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1546 impl
->hRef
, impl
->implflags
);
1552 static void dump_DispParms(const DISPPARAMS
* pdp
)
1556 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1558 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1560 TRACE("named args:\n");
1561 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1562 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1565 if (pdp
->cArgs
&& pdp
->rgvarg
)
1568 for (index
= 0; index
< pdp
->cArgs
; index
++)
1569 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1573 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1575 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1576 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1577 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1578 TRACE("kind:%s\n", typekind_desc
[pty
->typekind
]);
1579 TRACE("fct:%u var:%u impl:%u\n", pty
->cFuncs
, pty
->cVars
, pty
->cImplTypes
);
1580 TRACE("wTypeFlags: 0x%04x\n", pty
->wTypeFlags
);
1581 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1582 if (pty
->typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1584 dump_TLBFuncDesc(pty
->funcdescs
, pty
->cFuncs
);
1585 dump_TLBVarDesc(pty
->vardescs
, pty
->cVars
);
1586 dump_TLBImplType(pty
->impltypes
, pty
->cImplTypes
);
1589 static void dump_VARDESC(const VARDESC
*v
)
1591 MESSAGE("memid %d\n",v
->memid
);
1592 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1593 MESSAGE("oInst %d\n",v
->u
.oInst
);
1594 dump_ELEMDESC(&(v
->elemdescVar
));
1595 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1596 MESSAGE("varkind %d\n",v
->varkind
);
1599 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1601 /* VT_LPWSTR is largest type that, may appear in type description */
1602 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1603 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1604 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1605 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1606 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1607 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1608 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1609 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1612 static void TLB_abort(void)
1617 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1619 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1620 if (!ret
) ERR("cannot allocate memory\n");
1624 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1626 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1627 if (!ret
) ERR("cannot allocate memory\n");
1631 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1633 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1636 void heap_free(void *ptr
)
1638 HeapFree(GetProcessHeap(), 0, ptr
);
1641 /* returns the size required for a deep copy of a typedesc into a
1643 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1647 if (alloc_initial_space
)
1648 size
+= sizeof(TYPEDESC
);
1654 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1657 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1658 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1664 /* deep copy a typedesc into a flat buffer */
1665 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1670 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1679 dest
->u
.lptdesc
= buffer
;
1680 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1683 dest
->u
.lpadesc
= buffer
;
1684 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1685 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1686 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1692 /* free custom data allocated by MSFT_CustData */
1693 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1695 TLBCustData
*cd
, *cdn
;
1696 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1698 list_remove(&cd
->entry
);
1699 VariantClear(&cd
->data
);
1704 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1709 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1710 ret
= SysAllocStringLen(NULL
, len
- 1);
1711 if (!ret
) return ret
;
1712 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1716 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1717 UINT n
, MEMBERID memid
)
1720 if(funcdescs
->funcdesc
.memid
== memid
)
1728 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1729 UINT n
, MEMBERID memid
)
1732 if(vardescs
->vardesc
.memid
== memid
)
1740 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1741 UINT n
, const OLECHAR
*name
)
1744 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1752 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1754 TLBCustData
*cust_data
;
1755 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1756 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1761 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1762 UINT n
, const OLECHAR
*name
)
1765 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1773 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1775 list_init(&var_desc
->custdata_list
);
1778 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1782 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1787 TLBVarDesc_Constructor(&ret
[n
-1]);
1794 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1798 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1803 list_init(&ret
[n
-1].custdata_list
);
1810 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1812 list_init(&func_desc
->custdata_list
);
1815 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1819 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1824 TLBFuncDesc_Constructor(&ret
[n
-1]);
1831 static void TLBImplType_Constructor(TLBImplType
*impl
)
1833 list_init(&impl
->custdata_list
);
1836 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1840 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1845 TLBImplType_Constructor(&ret
[n
-1]);
1852 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1853 const GUID
*new_guid
, HREFTYPE hreftype
)
1857 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1858 if (IsEqualGUID(&guid
->guid
, new_guid
))
1862 guid
= heap_alloc(sizeof(TLBGuid
));
1866 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1867 guid
->hreftype
= hreftype
;
1869 list_add_tail(guid_list
, &guid
->entry
);
1874 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1876 TLBCustData
*cust_data
;
1888 return DISP_E_BADVARTYPE
;
1891 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1894 cust_data
= heap_alloc(sizeof(TLBCustData
));
1896 return E_OUTOFMEMORY
;
1898 cust_data
->guid
= tlbguid
;
1899 VariantInit(&cust_data
->data
);
1901 list_add_tail(custdata_list
, &cust_data
->entry
);
1903 VariantClear(&cust_data
->data
);
1905 return VariantCopy(&cust_data
->data
, var
);
1908 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1915 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1916 if (strcmpW(str
->str
, new_str
) == 0)
1920 str
= heap_alloc(sizeof(TLBString
));
1924 str
->str
= SysAllocString(new_str
);
1930 list_add_tail(string_list
, &str
->entry
);
1935 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1936 ULONG
*size
, WORD
*align
)
1942 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1946 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1948 ITypeInfo_Release(other
);
1953 *size
= attr
->cbSizeInstance
;
1955 *align
= attr
->cbAlignment
;
1957 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1958 ITypeInfo_Release(other
);
1963 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1964 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1966 ULONG i
, sub
, ptr_size
;
1969 ptr_size
= get_ptr_size(sys
);
2008 *size
= sizeof(DATE
);
2011 *size
= sizeof(VARIANT
);
2013 if(sys
== SYS_WIN32
)
2014 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2018 *size
= sizeof(DECIMAL
);
2025 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2026 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2027 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2032 case VT_USERDEFINED
:
2033 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2035 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2049 /**********************************************************************
2051 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2054 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2056 if (where
!= DO_NOT_SEEK
)
2058 where
+= pcx
->oStart
;
2059 if (where
> pcx
->length
)
2062 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2070 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2072 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2073 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2075 MSFT_Seek(pcx
, where
);
2076 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2077 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2082 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2087 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2088 FromLEDWords(buffer
, ret
);
2093 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2098 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2099 FromLEWords(buffer
, ret
);
2104 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2107 MSFT_GuidEntry entry
;
2110 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2112 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2115 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2117 guid
= heap_alloc(sizeof(TLBGuid
));
2119 guid
->offset
= offs
;
2120 guid
->guid
= entry
.guid
;
2121 guid
->hreftype
= entry
.hreftype
;
2123 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2125 offs
+= sizeof(MSFT_GuidEntry
);
2129 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2133 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2134 if(ret
->offset
== offset
){
2135 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2143 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2145 MSFT_NameIntro niName
;
2149 ERR_(typelib
)("bad offset %d\n", offset
);
2153 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2154 pcx
->pTblDir
->pNametab
.offset
+offset
);
2156 return niName
.hreftype
;
2159 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2162 MSFT_NameIntro intro
;
2164 int offs
= 0, lengthInChars
;
2166 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2170 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2173 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2174 intro
.namelen
&= 0xFF;
2175 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2177 len_piece
= (len_piece
+ 4) & ~0x3;
2181 string
= heap_alloc(len_piece
+ 1);
2182 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2183 string
[intro
.namelen
] = '\0';
2185 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2186 string
, -1, NULL
, 0);
2187 if (!lengthInChars
) {
2189 return E_UNEXPECTED
;
2192 tlbstr
= heap_alloc(sizeof(TLBString
));
2194 tlbstr
->offset
= offs
;
2195 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2196 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2200 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2206 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2210 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2211 if (tlbstr
->offset
== offset
) {
2212 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2220 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2224 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2225 if (tlbstr
->offset
== offset
) {
2226 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2235 * read a value and fill a VARIANT structure
2237 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2241 TRACE_(typelib
)("\n");
2243 if(offset
<0) { /* data are packed in here */
2244 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2245 V_I4(pVar
) = offset
& 0x3ffffff;
2248 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2249 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2250 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2251 switch (V_VT(pVar
)){
2252 case VT_EMPTY
: /* FIXME: is this right? */
2253 case VT_NULL
: /* FIXME: is this right? */
2254 case VT_I2
: /* this should not happen */
2265 case VT_VOID
: /* FIXME: is this right? */
2273 case VT_DECIMAL
: /* FIXME: is this right? */
2276 /* pointer types with known behaviour */
2279 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2281 V_BSTR(pVar
) = NULL
;
2283 ptr
= heap_alloc_zero(size
);
2284 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2285 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2286 /* FIXME: do we need a AtoW conversion here? */
2287 V_UNION(pVar
, bstrVal
[size
])='\0';
2288 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2293 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2300 case VT_USERDEFINED
:
2306 case VT_STREAMED_OBJECT
:
2307 case VT_STORED_OBJECT
:
2308 case VT_BLOB_OBJECT
:
2313 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2317 if(size
>0) /* (big|small) endian correct? */
2318 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2322 * create a linked list with custom data
2324 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2330 TRACE_(typelib
)("\n");
2332 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2336 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2337 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2338 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2339 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2340 list_add_head(custdata_list
, &pNew
->entry
);
2341 offset
= entry
.next
;
2346 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2349 pTd
->vt
=type
& VT_TYPEMASK
;
2351 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2353 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2356 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2358 return (invkind
== INVOKE_PROPERTYGET
||
2359 invkind
== INVOKE_PROPERTYPUT
||
2360 invkind
== INVOKE_PROPERTYPUTREF
);
2364 MSFT_DoFuncs(TLBContext
* pcx
,
2369 TLBFuncDesc
** pptfd
)
2372 * member information is stored in a data structure at offset
2373 * indicated by the memoffset field of the typeinfo structure
2374 * There are several distinctive parts.
2375 * The first part starts with a field that holds the total length
2376 * of this (first) part excluding this field. Then follow the records,
2377 * for each member there is one record.
2379 * The first entry is always the length of the record (including this
2381 * The rest of the record depends on the type of the member. If there is
2382 * a field indicating the member type (function, variable, interface, etc)
2383 * I have not found it yet. At this time we depend on the information
2384 * in the type info and the usual order how things are stored.
2386 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2389 * Third is an equal sized array with file offsets to the name entry
2392 * The fourth and last (?) part is an array with offsets to the records
2393 * in the first part of this file segment.
2396 int infolen
, nameoffset
, reclength
, i
;
2397 int recoffset
= offset
+ sizeof(INT
);
2399 char *recbuf
= heap_alloc(0xffff);
2400 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2401 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2403 TRACE_(typelib
)("\n");
2405 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2407 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2409 for ( i
= 0; i
< cFuncs
; i
++ )
2413 /* name, eventually add to a hash table */
2414 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2415 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2417 /* read the function information record */
2418 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2420 reclength
&= 0xffff;
2422 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2424 /* size without argument data */
2425 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2426 if (pFuncRec
->FKCCIC
& 0x1000)
2427 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2429 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2430 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2432 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2433 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2435 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2437 if (pFuncRec
->FKCCIC
& 0x2000 )
2439 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2440 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2441 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2444 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2447 ptfd
->Entry
= (TLBString
*)-1;
2449 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2450 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2452 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2453 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2455 /* fill the FuncDesc Structure */
2456 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2457 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2459 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2460 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2461 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2462 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2463 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2464 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2465 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2467 /* nameoffset is sometimes -1 on the second half of a propget/propput
2468 * pair of functions */
2469 if ((nameoffset
== -1) && (i
> 0) &&
2470 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2471 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2472 ptfd
->Name
= ptfd_prev
->Name
;
2474 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2478 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2480 /* do the parameters/arguments */
2481 if(pFuncRec
->nrargs
)
2484 MSFT_ParameterInfo paraminfo
;
2486 ptfd
->funcdesc
.lprgelemdescParam
=
2487 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2489 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2491 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2492 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2494 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2496 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2502 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2505 if (paraminfo
.oName
!= -1)
2506 ptfd
->pParamDesc
[j
].Name
=
2507 MSFT_ReadName( pcx
, paraminfo
.oName
);
2508 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2511 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2512 (pFuncRec
->FKCCIC
& 0x1000) )
2514 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2516 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2518 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2520 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2521 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2523 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2527 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2530 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2531 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2532 pFuncRec
->FKCCIC
& 0x80 )
2535 pFuncRec
->oArgCustData
[j
],
2536 &ptfd
->pParamDesc
[j
].custdata_list
);
2539 /* SEEK value = jump to offset,
2540 * from there jump to the end of record,
2541 * go back by (j-1) arguments
2543 MSFT_ReadLEDWords( ¶minfo
,
2544 sizeof(MSFT_ParameterInfo
), pcx
,
2545 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2546 * sizeof(MSFT_ParameterInfo
)));
2550 /* scode is not used: archaic win16 stuff FIXME: right? */
2551 ptfd
->funcdesc
.cScodes
= 0 ;
2552 ptfd
->funcdesc
.lprgscode
= NULL
;
2556 recoffset
+= reclength
;
2561 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2562 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2564 int infolen
, nameoffset
, reclength
;
2566 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2571 TRACE_(typelib
)("\n");
2573 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2574 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2575 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2576 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2577 recoffset
+= offset
+sizeof(INT
);
2578 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2579 /* name, eventually add to a hash table */
2580 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2581 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2582 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2583 /* read the variable information record */
2584 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2586 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2589 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2590 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2592 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2593 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2595 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2596 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2598 /* fill the VarDesc Structure */
2599 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2600 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2601 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2602 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2603 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2604 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2605 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2606 if(pVarRec
->VarKind
== VAR_CONST
){
2607 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2608 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2609 pVarRec
->OffsValue
, pcx
);
2611 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2612 recoffset
+= reclength
;
2616 /* process Implemented Interfaces of a com class */
2617 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2621 MSFT_RefRecord refrec
;
2624 TRACE_(typelib
)("\n");
2626 pTI
->impltypes
= TLBImplType_Alloc(count
);
2627 pImpl
= pTI
->impltypes
;
2628 for(i
=0;i
<count
;i
++){
2629 if(offset
<0) break; /* paranoia */
2630 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2631 pImpl
->hRef
= refrec
.reftype
;
2632 pImpl
->implflags
=refrec
.flags
;
2633 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2634 offset
=refrec
.onext
;
2640 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2641 * and some structures, and fix the alignment */
2642 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2644 if(info
->typekind
== TKIND_ALIAS
){
2645 switch(info
->tdescAlias
->vt
){
2653 info
->cbSizeInstance
= sizeof(void*);
2654 info
->cbAlignment
= sizeof(void*);
2657 case VT_USERDEFINED
:
2658 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->cbSizeInstance
, &info
->cbAlignment
);
2661 info
->cbSizeInstance
= sizeof(VARIANT
);
2662 info
->cbAlignment
= 8;
2664 if(info
->cbSizeInstance
< sizeof(void*))
2665 info
->cbAlignment
= info
->cbSizeInstance
;
2667 info
->cbAlignment
= sizeof(void*);
2670 }else if(info
->typekind
== TKIND_INTERFACE
||
2671 info
->typekind
== TKIND_DISPATCH
||
2672 info
->typekind
== TKIND_COCLASS
){
2673 info
->cbSizeInstance
= sizeof(void*);
2674 info
->cbAlignment
= sizeof(void*);
2680 * process a typeinfo record
2682 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2685 ITypeLibImpl
* pLibInfo
)
2687 MSFT_TypeInfoBase tiBase
;
2688 ITypeInfoImpl
*ptiRet
;
2690 TRACE_(typelib
)("count=%u\n", count
);
2692 ptiRet
= ITypeInfoImpl_Constructor();
2693 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2694 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2696 /* this is where we are coming from */
2697 ptiRet
->pTypeLib
= pLibInfo
;
2698 ptiRet
->index
=count
;
2700 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2701 ptiRet
->lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2702 ptiRet
->lpstrSchema
=NULL
; /* reserved */
2703 ptiRet
->cbSizeInstance
=tiBase
.size
;
2704 ptiRet
->typekind
=tiBase
.typekind
& 0xF;
2705 ptiRet
->cFuncs
=LOWORD(tiBase
.cElement
);
2706 ptiRet
->cVars
=HIWORD(tiBase
.cElement
);
2707 ptiRet
->cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2708 ptiRet
->wTypeFlags
=tiBase
.flags
;
2709 ptiRet
->wMajorVerNum
=LOWORD(tiBase
.version
);
2710 ptiRet
->wMinorVerNum
=HIWORD(tiBase
.version
);
2711 ptiRet
->cImplTypes
=tiBase
.cImplTypes
;
2712 ptiRet
->cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2713 if(ptiRet
->typekind
== TKIND_ALIAS
){
2715 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2716 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2717 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2721 /* IDLDESC idldescType; *//* never saw this one != zero */
2723 /* name, eventually add to a hash table */
2724 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2725 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2726 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2728 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2729 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2730 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2732 if (ptiRet
->typekind
== TKIND_MODULE
)
2733 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2735 /* note: InfoType's Help file and HelpStringDll come from the containing
2736 * library. Further HelpString and Docstring appear to be the same thing :(
2739 if(ptiRet
->cFuncs
>0 )
2740 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->cFuncs
,
2742 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2744 if(ptiRet
->cVars
>0 )
2745 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->cFuncs
,
2747 tiBase
.memoffset
, &ptiRet
->vardescs
);
2748 if(ptiRet
->cImplTypes
>0 ) {
2749 switch(ptiRet
->typekind
)
2752 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->cImplTypes
,
2755 case TKIND_DISPATCH
:
2756 /* This is not -1 when the interface is a non-base dual interface or
2757 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2758 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2762 if (tiBase
.datatype1
!= -1)
2764 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2765 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2769 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2770 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2774 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2776 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2777 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2778 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2779 typekind_desc
[ptiRet
->typekind
]);
2780 if (TRACE_ON(typelib
))
2781 dump_TypeInfo(ptiRet
);
2786 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2789 INT16 len_str
, len_piece
;
2790 int offs
= 0, lengthInChars
;
2792 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2796 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2799 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2800 len_piece
= len_str
+ sizeof(INT16
);
2802 len_piece
= (len_piece
+ 4) & ~0x3;
2806 string
= heap_alloc(len_piece
+ 1);
2807 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2808 string
[len_str
] = '\0';
2810 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2811 string
, -1, NULL
, 0);
2812 if (!lengthInChars
) {
2814 return E_UNEXPECTED
;
2817 tlbstr
= heap_alloc(sizeof(TLBString
));
2819 tlbstr
->offset
= offs
;
2820 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2821 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2825 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2831 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2836 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2837 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2838 MSFT_ImpInfo impinfo
;
2841 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2843 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2844 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2846 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2847 if(pImpLib
->offset
==impinfo
.oImpFile
)
2850 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2851 ref
->reference
= offs
;
2852 ref
->pImpTLInfo
= pImpLib
;
2853 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2854 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2855 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2856 ref
->index
= TLB_REF_USE_GUID
;
2858 ref
->index
= impinfo
.oGuid
;
2860 ERR("Cannot find a reference\n");
2861 ref
->reference
= -1;
2862 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2865 offs
+= sizeof(impinfo
);
2871 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2872 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2873 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2876 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2877 static CRITICAL_SECTION cache_section
;
2878 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2880 0, 0, &cache_section
,
2881 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2882 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2884 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2887 typedef struct TLB_PEFile
2889 IUnknown IUnknown_iface
;
2892 HRSRC typelib_resource
;
2893 HGLOBAL typelib_global
;
2894 LPVOID typelib_base
;
2897 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2899 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2902 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2904 if (IsEqualIID(riid
, &IID_IUnknown
))
2907 IUnknown_AddRef(iface
);
2911 return E_NOINTERFACE
;
2914 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2916 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2917 return InterlockedIncrement(&This
->refs
);
2920 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2922 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2923 ULONG refs
= InterlockedDecrement(&This
->refs
);
2926 if (This
->typelib_global
)
2927 FreeResource(This
->typelib_global
);
2929 FreeLibrary(This
->dll
);
2935 static const IUnknownVtbl TLB_PEFile_Vtable
=
2937 TLB_PEFile_QueryInterface
,
2942 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2945 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2947 This
= heap_alloc(sizeof(TLB_PEFile
));
2949 return E_OUTOFMEMORY
;
2951 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2954 This
->typelib_resource
= NULL
;
2955 This
->typelib_global
= NULL
;
2956 This
->typelib_base
= NULL
;
2958 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2959 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2963 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2964 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2965 if (This
->typelib_resource
)
2967 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2968 if (This
->typelib_global
)
2970 This
->typelib_base
= LockResource(This
->typelib_global
);
2972 if (This
->typelib_base
)
2974 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2975 *ppBase
= This
->typelib_base
;
2976 *ppFile
= &This
->IUnknown_iface
;
2982 TRACE("No TYPELIB resource found\n");
2986 TLB_PEFile_Release(&This
->IUnknown_iface
);
2990 typedef struct TLB_NEFile
2992 IUnknown IUnknown_iface
;
2994 LPVOID typelib_base
;
2997 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2999 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
3002 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3004 if (IsEqualIID(riid
, &IID_IUnknown
))
3007 IUnknown_AddRef(iface
);
3011 return E_NOINTERFACE
;
3014 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
3016 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3017 return InterlockedIncrement(&This
->refs
);
3020 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
3022 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3023 ULONG refs
= InterlockedDecrement(&This
->refs
);
3026 heap_free(This
->typelib_base
);
3032 static const IUnknownVtbl TLB_NEFile_Vtable
=
3034 TLB_NEFile_QueryInterface
,
3039 /***********************************************************************
3040 * read_xx_header [internal]
3042 static int read_xx_header( HFILE lzfd
)
3044 IMAGE_DOS_HEADER mzh
;
3047 LZSeek( lzfd
, 0, SEEK_SET
);
3048 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3050 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3053 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3054 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3057 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3059 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3060 return IMAGE_OS2_SIGNATURE
;
3061 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3062 return IMAGE_NT_SIGNATURE
;
3065 WARN("Can't handle %s files.\n", magic
);
3070 /***********************************************************************
3071 * find_ne_resource [internal]
3073 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3074 DWORD
*resLen
, DWORD
*resOff
)
3076 IMAGE_OS2_HEADER nehd
;
3077 NE_TYPEINFO
*typeInfo
;
3078 NE_NAMEINFO
*nameInfo
;
3084 /* Read in NE header */
3085 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3086 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3088 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3091 TRACE("No resources in NE dll\n" );
3095 /* Read in resource table */
3096 resTab
= heap_alloc( resTabSize
);
3097 if ( !resTab
) return FALSE
;
3099 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3100 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3102 heap_free( resTab
);
3107 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3109 if (!IS_INTRESOURCE(typeid)) /* named type */
3111 BYTE len
= strlen( typeid );
3112 while (typeInfo
->type_id
)
3114 if (!(typeInfo
->type_id
& 0x8000))
3116 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3117 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
3119 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3120 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3123 else /* numeric type id */
3125 WORD id
= LOWORD(typeid) | 0x8000;
3126 while (typeInfo
->type_id
)
3128 if (typeInfo
->type_id
== id
) goto found_type
;
3129 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3130 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3133 TRACE("No typeid entry found for %p\n", typeid );
3134 heap_free( resTab
);
3138 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3140 if (!IS_INTRESOURCE(resid
)) /* named resource */
3142 BYTE len
= strlen( resid
);
3143 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3145 BYTE
*p
= resTab
+ nameInfo
->id
;
3146 if (nameInfo
->id
& 0x8000) continue;
3147 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3150 else /* numeric resource id */
3152 WORD id
= LOWORD(resid
) | 0x8000;
3153 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3154 if (nameInfo
->id
== id
) goto found_name
;
3156 TRACE("No resid entry found for %p\n", typeid );
3157 heap_free( resTab
);
3161 /* Return resource data */
3162 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3163 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3165 heap_free( resTab
);
3169 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3173 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3176 This
= heap_alloc(sizeof(TLB_NEFile
));
3177 if (!This
) return E_OUTOFMEMORY
;
3179 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3181 This
->typelib_base
= NULL
;
3183 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3184 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3186 DWORD reslen
, offset
;
3187 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3189 This
->typelib_base
= heap_alloc(reslen
);
3190 if( !This
->typelib_base
)
3194 LZSeek( lzfd
, offset
, SEEK_SET
);
3195 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3197 *ppBase
= This
->typelib_base
;
3198 *pdwTLBLength
= reslen
;
3199 *ppFile
= &This
->IUnknown_iface
;
3205 if( lzfd
>= 0) LZClose( lzfd
);
3206 TLB_NEFile_Release(&This
->IUnknown_iface
);
3210 typedef struct TLB_Mapping
3212 IUnknown IUnknown_iface
;
3216 LPVOID typelib_base
;
3219 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3221 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3224 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3226 if (IsEqualIID(riid
, &IID_IUnknown
))
3229 IUnknown_AddRef(iface
);
3233 return E_NOINTERFACE
;
3236 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3238 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3239 return InterlockedIncrement(&This
->refs
);
3242 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3244 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3245 ULONG refs
= InterlockedDecrement(&This
->refs
);
3248 if (This
->typelib_base
)
3249 UnmapViewOfFile(This
->typelib_base
);
3251 CloseHandle(This
->mapping
);
3252 if (This
->file
!= INVALID_HANDLE_VALUE
)
3253 CloseHandle(This
->file
);
3259 static const IUnknownVtbl TLB_Mapping_Vtable
=
3261 TLB_Mapping_QueryInterface
,
3266 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3270 This
= heap_alloc(sizeof(TLB_Mapping
));
3272 return E_OUTOFMEMORY
;
3274 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3276 This
->file
= INVALID_HANDLE_VALUE
;
3277 This
->mapping
= NULL
;
3278 This
->typelib_base
= NULL
;
3280 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3281 if (INVALID_HANDLE_VALUE
!= This
->file
)
3283 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3286 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3287 if(This
->typelib_base
)
3289 /* retrieve file size */
3290 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3291 *ppBase
= This
->typelib_base
;
3292 *ppFile
= &This
->IUnknown_iface
;
3298 IUnknown_Release(&This
->IUnknown_iface
);
3299 return TYPE_E_CANTLOADLIBRARY
;
3302 /****************************************************************************
3305 * find the type of the typelib file and map the typelib resource into
3309 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3310 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3312 ITypeLibImpl
*entry
;
3315 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3316 LPVOID pBase
= NULL
;
3317 DWORD dwTLBLength
= 0;
3318 IUnknown
*pFile
= NULL
;
3323 index_str
= strrchrW(pszFileName
, '\\');
3324 if(index_str
&& *++index_str
!= '\0')
3327 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3328 if(*end_ptr
== '\0')
3330 int str_len
= index_str
- pszFileName
- 1;
3332 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3333 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3338 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3340 if(strchrW(file
, '\\'))
3342 lstrcpyW(pszPath
, file
);
3346 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3347 pszPath
[len
] = '\\';
3348 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3352 if(file
!= pszFileName
) heap_free(file
);
3354 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3355 if(h
!= INVALID_HANDLE_VALUE
){
3356 FILE_NAME_INFORMATION size_info
;
3359 /* GetFileInformationByHandleEx returns the path of the file without
3360 * WOW64 redirection */
3361 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, &size_info
, sizeof(size_info
));
3362 if(br
|| GetLastError() == ERROR_MORE_DATA
){
3363 FILE_NAME_INFORMATION
*info
;
3364 DWORD size
= sizeof(*info
) + size_info
.FileNameLength
+ sizeof(WCHAR
);
3366 info
= HeapAlloc(GetProcessHeap(), 0, size
);
3368 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, info
, size
);
3370 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3371 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3374 HeapFree(GetProcessHeap(), 0, info
);
3380 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3382 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3383 EnterCriticalSection(&cache_section
);
3384 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3386 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3388 TRACE("cache hit\n");
3389 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3390 ITypeLib2_AddRef(*ppTypeLib
);
3391 LeaveCriticalSection(&cache_section
);
3395 LeaveCriticalSection(&cache_section
);
3397 /* now actually load and parse the typelib */
3399 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3400 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3401 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3402 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3403 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3406 if (dwTLBLength
>= 4)
3408 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3409 if (dwSignature
== MSFT_SIGNATURE
)
3410 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3411 else if (dwSignature
== SLTG_SIGNATURE
)
3412 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3415 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3416 ret
= TYPE_E_CANTLOADLIBRARY
;
3420 ret
= TYPE_E_CANTLOADLIBRARY
;
3421 IUnknown_Release(pFile
);
3425 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3427 TRACE("adding to cache\n");
3428 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3429 lstrcpyW(impl
->path
, pszPath
);
3430 /* We should really canonicalise the path here. */
3431 impl
->index
= index
;
3433 /* FIXME: check if it has added already in the meantime */
3434 EnterCriticalSection(&cache_section
);
3435 list_add_head(&tlb_cache
, &impl
->entry
);
3436 LeaveCriticalSection(&cache_section
);
3442 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3444 ret
= TYPE_E_CANTLOADLIBRARY
;
3451 /*================== ITypeLib(2) Methods ===================================*/
3453 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3455 ITypeLibImpl
* pTypeLibImpl
;
3457 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3458 if (!pTypeLibImpl
) return NULL
;
3460 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3461 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3462 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3463 pTypeLibImpl
->ref
= 1;
3465 list_init(&pTypeLibImpl
->implib_list
);
3466 list_init(&pTypeLibImpl
->custdata_list
);
3467 list_init(&pTypeLibImpl
->name_list
);
3468 list_init(&pTypeLibImpl
->string_list
);
3469 list_init(&pTypeLibImpl
->guid_list
);
3470 list_init(&pTypeLibImpl
->ref_list
);
3471 pTypeLibImpl
->dispatch_href
= -1;
3473 return pTypeLibImpl
;
3476 /****************************************************************************
3477 * ITypeLib2_Constructor_MSFT
3479 * loading an MSFT typelib from an in-memory image
3481 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3485 MSFT_Header tlbHeader
;
3486 MSFT_SegDir tlbSegDir
;
3487 ITypeLibImpl
* pTypeLibImpl
;
3490 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3492 pTypeLibImpl
= TypeLibImpl_Constructor();
3493 if (!pTypeLibImpl
) return NULL
;
3495 /* get pointer to beginning of typelib data */
3499 cx
.pLibInfo
= pTypeLibImpl
;
3500 cx
.length
= dwTLBLength
;
3503 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3504 TRACE_(typelib
)("header:\n");
3505 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3506 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3507 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3510 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3512 /* there is a small amount of information here until the next important
3514 * the segment directory . Try to calculate the amount of data */
3515 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3517 /* now read the segment directory */
3518 TRACE("read segment directory (at %d)\n",lPSegDir
);
3519 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3520 cx
.pTblDir
= &tlbSegDir
;
3522 /* just check two entries */
3523 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3525 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3526 heap_free(pTypeLibImpl
);
3530 MSFT_ReadAllNames(&cx
);
3531 MSFT_ReadAllStrings(&cx
);
3532 MSFT_ReadAllGuids(&cx
);
3534 /* now fill our internal data */
3535 /* TLIBATTR fields */
3536 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3538 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3539 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3540 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3541 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3542 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3544 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3545 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3547 /* name, eventually add to a hash table */
3548 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3551 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3552 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3554 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3557 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3558 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3561 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3564 if(tlbHeader
.CustomDataOffset
>= 0)
3566 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3569 /* fill in type descriptions */
3570 if(tlbSegDir
.pTypdescTab
.length
> 0)
3572 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3574 pTypeLibImpl
->ctTypeDesc
= cTD
;
3575 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3576 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3579 /* FIXME: add several sanity checks here */
3580 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3581 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3583 /* FIXME: check safearray */
3585 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3587 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3589 else if(td
[0] == VT_CARRAY
)
3591 /* array descr table here */
3592 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3594 else if(td
[0] == VT_USERDEFINED
)
3596 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3598 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3601 /* second time around to fill the array subscript info */
3604 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3605 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3607 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3608 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3611 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3613 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3615 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3617 for(j
= 0; j
<td
[2]; j
++)
3619 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3620 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3621 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3622 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3627 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3628 ERR("didn't find array description data\n");
3633 /* imported type libs */
3634 if(tlbSegDir
.pImpFiles
.offset
>0)
3637 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3640 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3644 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3645 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3646 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3648 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3649 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3650 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3651 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3654 name
= heap_alloc_zero(size
+1);
3655 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3656 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3659 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3660 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3662 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3666 MSFT_ReadAllRefs(&cx
);
3668 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3671 if(tlbHeader
.nrtypeinfos
>= 0 )
3673 ITypeInfoImpl
**ppTI
;
3675 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3677 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3679 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3682 (pTypeLibImpl
->TypeInfoCount
)++;
3687 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3688 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3689 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3693 TRACE("(%p)\n", pTypeLibImpl
);
3694 return &pTypeLibImpl
->ITypeLib2_iface
;
3698 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3704 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3705 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3709 guid
->Data4
[0] = s
>> 8;
3710 guid
->Data4
[1] = s
& 0xff;
3713 for(i
= 0; i
< 6; i
++) {
3714 memcpy(b
, str
+ 24 + 2 * i
, 2);
3715 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3720 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3727 bytelen
= *(const WORD
*)ptr
;
3728 if(bytelen
== 0xffff) return 2;
3730 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3731 tmp_str
= SysAllocStringLen(NULL
, len
);
3733 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3734 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3735 SysFreeString(tmp_str
);
3740 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3745 bytelen
= *(const WORD
*)ptr
;
3746 if(bytelen
== 0xffff) return 2;
3747 *str
= heap_alloc(bytelen
+ 1);
3748 memcpy(*str
, ptr
+ 2, bytelen
);
3749 (*str
)[bytelen
] = '\0';
3753 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3758 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3759 if (tlbstr
->offset
== offset
)
3763 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3764 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3765 SysFreeString(tmp_str
);
3770 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3772 char *ptr
= pLibBlk
;
3775 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3776 FIXME("libblk magic = %04x\n", w
);
3781 if((w
= *(WORD
*)ptr
) != 0xffff) {
3782 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3787 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3789 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3791 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3794 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3795 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3798 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3799 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3801 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3804 ptr
+= 4; /* skip res12 */
3806 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3809 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3812 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3815 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3816 ptr
+= sizeof(GUID
);
3818 return ptr
- (char*)pLibBlk
;
3821 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3826 } sltg_ref_lookup_t
;
3828 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3829 HREFTYPE
*typelib_ref
)
3831 if(table
&& typeinfo_ref
< table
->num
)
3833 *typelib_ref
= table
->refs
[typeinfo_ref
];
3837 ERR_(typelib
)("Unable to find reference\n");
3842 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3847 if((*pType
& 0xe00) == 0xe00) {
3849 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3850 pTD
= pTD
->u
.lptdesc
;
3852 switch(*pType
& 0x3f) {
3855 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3856 pTD
= pTD
->u
.lptdesc
;
3859 case VT_USERDEFINED
:
3860 pTD
->vt
= VT_USERDEFINED
;
3861 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3867 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3870 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3872 pTD
->vt
= VT_CARRAY
;
3873 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3874 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3875 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3876 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3878 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3884 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3888 pTD
->vt
= VT_SAFEARRAY
;
3889 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3890 pTD
= pTD
->u
.lptdesc
;
3894 pTD
->vt
= *pType
& 0x3f;
3903 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3904 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3906 /* Handle [in/out] first */
3907 if((*pType
& 0xc000) == 0xc000)
3908 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3909 else if(*pType
& 0x8000)
3910 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3911 else if(*pType
& 0x4000)
3912 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3914 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3917 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3920 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3922 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3926 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3931 TLBRefType
*ref_type
;
3932 sltg_ref_lookup_t
*table
;
3933 HREFTYPE typelib_ref
;
3935 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3936 FIXME("Ref magic = %x\n", pRef
->magic
);
3939 name
= ( (char*)pRef
->names
+ pRef
->number
);
3941 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3942 table
->num
= pRef
->number
>> 3;
3944 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3946 /* We don't want the first href to be 0 */
3947 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3949 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3951 unsigned int lib_offs
, type_num
;
3953 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3955 name
+= SLTG_ReadStringA(name
, &refname
);
3956 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3957 FIXME_(typelib
)("Can't sscanf ref\n");
3958 if(lib_offs
!= 0xffff) {
3961 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3962 if(import
->offset
== lib_offs
)
3965 if(&import
->entry
== &pTL
->implib_list
) {
3966 char fname
[MAX_PATH
+1];
3970 import
= heap_alloc_zero(sizeof(*import
));
3971 import
->offset
= lib_offs
;
3972 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3973 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3974 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3975 &import
->wVersionMajor
,
3976 &import
->wVersionMinor
,
3977 &import
->lcid
, fname
) != 4) {
3978 FIXME_(typelib
)("can't sscanf ref %s\n",
3979 pNameTable
+ lib_offs
+ 40);
3981 len
= strlen(fname
);
3982 if(fname
[len
-1] != '#')
3983 FIXME("fname = %s\n", fname
);
3984 fname
[len
-1] = '\0';
3985 import
->name
= TLB_MultiByteToBSTR(fname
);
3986 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3988 ref_type
->pImpTLInfo
= import
;
3990 /* Store a reference to IDispatch */
3991 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3992 pTL
->dispatch_href
= typelib_ref
;
3994 } else { /* internal ref */
3995 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3997 ref_type
->reference
= typelib_ref
;
3998 ref_type
->index
= type_num
;
4001 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
4003 table
->refs
[ref
] = typelib_ref
;
4006 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
4007 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
4008 dump_TLBRefType(pTL
);
4012 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
4013 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
4015 SLTG_ImplInfo
*info
;
4016 TLBImplType
*pImplType
;
4017 /* I don't really get this structure, usually it's 0x16 bytes
4018 long, but iuser.tlb contains some that are 0x18 bytes long.
4019 That's ok because we can use the next ptr to jump to the next
4020 one. But how do we know the length of the last one? The WORD
4021 at offs 0x8 might be the clue. For now I'm just assuming that
4022 the last one is the regular 0x16 bytes. */
4024 info
= (SLTG_ImplInfo
*)pBlk
;
4027 if(info
->next
== 0xffff)
4029 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4032 info
= (SLTG_ImplInfo
*)pBlk
;
4033 pTI
->impltypes
= TLBImplType_Alloc(pTI
->cImplTypes
);
4034 pImplType
= pTI
->impltypes
;
4036 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4037 pImplType
->implflags
= info
->impltypeflags
;
4040 if(info
->next
== 0xffff)
4043 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4044 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4046 info
++; /* see comment at top of function */
4050 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4051 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4053 TLBVarDesc
*pVarDesc
;
4054 const TLBString
*prevName
= NULL
;
4055 SLTG_Variable
*pItem
;
4059 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4061 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4062 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4064 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4066 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4067 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4068 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4072 if (pItem
->name
== 0xfffe)
4073 pVarDesc
->Name
= prevName
;
4075 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4077 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4078 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4079 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4081 if(pItem
->flags
& 0x02)
4082 pType
= &pItem
->type
;
4084 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4086 if (pItem
->flags
& ~0xda)
4087 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4089 SLTG_DoElem(pType
, pBlk
,
4090 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4092 if (TRACE_ON(typelib
)) {
4094 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4095 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4098 if (pItem
->flags
& 0x40) {
4099 TRACE_(typelib
)("VAR_DISPATCH\n");
4100 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4102 else if (pItem
->flags
& 0x10) {
4103 TRACE_(typelib
)("VAR_CONST\n");
4104 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4105 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4106 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4107 if (pItem
->flags
& 0x08)
4108 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4110 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4116 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4118 TRACE_(typelib
)("len = %u\n", len
);
4119 if (len
== 0xffff) {
4122 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4123 str
= SysAllocStringLen(NULL
, alloc_len
);
4124 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4126 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4127 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4136 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4137 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4140 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4145 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4146 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4147 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4150 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4151 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4153 if (pItem
->flags
& 0x80)
4154 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4156 prevName
= pVarDesc
->Name
;
4161 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4162 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4164 SLTG_Function
*pFunc
;
4166 TLBFuncDesc
*pFuncDesc
;
4168 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4170 pFuncDesc
= pTI
->funcdescs
;
4171 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4172 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4177 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4178 case SLTG_FUNCTION_MAGIC
:
4179 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4181 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4182 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4184 case SLTG_STATIC_FUNCTION_MAGIC
:
4185 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4188 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4191 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4193 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4194 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4195 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4196 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4197 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4198 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4200 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4201 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4203 if(pFunc
->retnextopt
& 0x80)
4204 pType
= &pFunc
->rettype
;
4206 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4208 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4210 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4211 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4212 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4214 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4216 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4217 char *paramName
= pNameTable
+ *pArg
;
4219 /* If arg type follows then paramName points to the 2nd
4220 letter of the name, else the next WORD is an offset to
4221 the arg type and paramName points to the first letter.
4222 So let's take one char off paramName and see if we're
4223 pointing at an alpha-numeric char. However if *pArg is
4224 0xffff or 0xfffe then the param has no name, the former
4225 meaning that the next WORD is the type, the latter
4226 meaning that the next WORD is an offset to the type. */
4231 else if(*pArg
== 0xfffe) {
4235 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4240 if(HaveOffs
) { /* the next word is an offset to type */
4241 pType
= (WORD
*)(pBlk
+ *pArg
);
4242 SLTG_DoElem(pType
, pBlk
,
4243 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4248 pArg
= SLTG_DoElem(pArg
, pBlk
,
4249 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4252 /* Are we an optional param ? */
4253 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4254 pFuncDesc
->funcdesc
.cParamsOpt
)
4255 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4258 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4259 paramName
- pNameTable
, pTI
->pTypeLib
);
4261 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4265 pTI
->cFuncs
= cFuncs
;
4268 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4269 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4270 SLTG_TypeInfoTail
*pTITail
)
4273 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4275 if(pTIHeader
->href_table
!= 0xffffffff) {
4276 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4282 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4283 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4285 heap_free(ref_lookup
);
4289 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4290 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4291 const SLTG_TypeInfoTail
*pTITail
)
4294 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4296 if(pTIHeader
->href_table
!= 0xffffffff) {
4297 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4303 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4304 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4307 if (pTITail
->funcs_off
!= 0xffff)
4308 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4310 heap_free(ref_lookup
);
4312 if (TRACE_ON(typelib
))
4313 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4316 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4317 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4318 const SLTG_TypeInfoTail
*pTITail
)
4320 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4323 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4324 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4325 const SLTG_TypeInfoTail
*pTITail
)
4328 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4330 if (pTITail
->simple_alias
) {
4331 /* if simple alias, no more processing required */
4332 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4333 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4337 if(pTIHeader
->href_table
!= 0xffffffff) {
4338 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4342 /* otherwise it is an offset to a type */
4343 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4345 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4346 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4348 heap_free(ref_lookup
);
4351 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4352 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4353 const SLTG_TypeInfoTail
*pTITail
)
4355 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4356 if (pTIHeader
->href_table
!= 0xffffffff)
4357 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4360 if (pTITail
->vars_off
!= 0xffff)
4361 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4363 if (pTITail
->funcs_off
!= 0xffff)
4364 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4366 if (pTITail
->impls_off
!= 0xffff)
4367 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4369 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4370 * of dispinterface functions including the IDispatch ones, so
4371 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4372 pTI
->cbSizeVft
= pTI
->cFuncs
* pTI
->pTypeLib
->ptr_size
;
4374 heap_free(ref_lookup
);
4375 if (TRACE_ON(typelib
))
4376 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4379 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4380 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4381 const SLTG_TypeInfoTail
*pTITail
)
4383 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4386 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4387 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4388 const SLTG_TypeInfoTail
*pTITail
)
4390 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4391 if (pTIHeader
->href_table
!= 0xffffffff)
4392 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4395 if (pTITail
->vars_off
!= 0xffff)
4396 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4398 if (pTITail
->funcs_off
!= 0xffff)
4399 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4400 heap_free(ref_lookup
);
4401 if (TRACE_ON(typelib
))
4405 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4406 manageable copy of it into this */
4419 } SLTG_InternalOtherTypeInfo
;
4421 /****************************************************************************
4422 * ITypeLib2_Constructor_SLTG
4424 * loading a SLTG typelib from an in-memory image
4426 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4428 ITypeLibImpl
*pTypeLibImpl
;
4429 SLTG_Header
*pHeader
;
4430 SLTG_BlkEntry
*pBlkEntry
;
4434 LPVOID pBlk
, pFirstBlk
;
4435 SLTG_LibBlk
*pLibBlk
;
4436 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4437 char *pAfterOTIBlks
= NULL
;
4438 char *pNameTable
, *ptr
;
4441 ITypeInfoImpl
**ppTypeInfoImpl
;
4443 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4446 pTypeLibImpl
= TypeLibImpl_Constructor();
4447 if (!pTypeLibImpl
) return NULL
;
4451 TRACE_(typelib
)("header:\n");
4452 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4453 pHeader
->nrOfFileBlks
);
4454 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4455 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4456 pHeader
->SLTG_magic
);
4460 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4461 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4463 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4464 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4466 /* Next we have a magic block */
4467 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4469 /* Let's see if we're still in sync */
4470 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4471 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4472 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4475 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4476 sizeof(SLTG_DIR_MAGIC
))) {
4477 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4481 pIndex
= (SLTG_Index
*)(pMagic
+1);
4483 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4485 pFirstBlk
= pPad9
+ 1;
4487 /* We'll set up a ptr to the main library block, which is the last one. */
4489 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4490 pBlkEntry
[order
].next
!= 0;
4491 order
= pBlkEntry
[order
].next
- 1, i
++) {
4492 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4496 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4498 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4503 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4505 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4508 ptr
= (char*)pLibBlk
+ len
;
4510 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4514 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4516 w
= *(WORD
*)(ptr
+ 2);
4519 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4520 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4521 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4523 w
= *(WORD
*)(ptr
+ 4 + len
);
4525 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4527 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4528 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4529 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4531 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4532 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4533 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4535 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4536 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4539 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4540 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4541 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4542 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4543 len
+= sizeof(SLTG_OtherTypeInfo
);
4547 pAfterOTIBlks
= ptr
;
4549 /* Skip this WORD and get the next DWORD */
4550 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4552 /* Now add this to pLibBLk look at what we're pointing at and
4553 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4554 dust and we should be pointing at the beginning of the name
4557 pNameTable
= (char*)pLibBlk
+ len
;
4559 switch(*(WORD
*)pNameTable
) {
4566 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4570 pNameTable
+= 0x216;
4574 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4576 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4579 /* Hopefully we now have enough ptrs set up to actually read in
4580 some TypeInfos. It's not clear which order to do them in, so
4581 I'll just follow the links along the BlkEntry chain and read
4582 them in the order in which they are in the file */
4584 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4585 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4587 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4588 pBlkEntry
[order
].next
!= 0;
4589 order
= pBlkEntry
[order
].next
- 1, i
++) {
4591 SLTG_TypeInfoHeader
*pTIHeader
;
4592 SLTG_TypeInfoTail
*pTITail
;
4593 SLTG_MemberHeader
*pMemHeader
;
4595 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4596 FIXME_(typelib
)("Index strings don't match\n");
4597 heap_free(pOtherTypeInfoBlks
);
4602 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4603 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4604 heap_free(pOtherTypeInfoBlks
);
4607 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4608 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4609 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4611 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4612 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4613 (*ppTypeInfoImpl
)->index
= i
;
4614 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4615 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4616 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4617 (*ppTypeInfoImpl
)->typekind
= pTIHeader
->typekind
;
4618 (*ppTypeInfoImpl
)->wMajorVerNum
= pTIHeader
->major_version
;
4619 (*ppTypeInfoImpl
)->wMinorVerNum
= pTIHeader
->minor_version
;
4620 (*ppTypeInfoImpl
)->wTypeFlags
=
4621 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4623 if((*ppTypeInfoImpl
)->wTypeFlags
& TYPEFLAG_FDUAL
)
4624 (*ppTypeInfoImpl
)->typekind
= TKIND_DISPATCH
;
4626 if((pTIHeader
->typeflags1
& 7) != 2)
4627 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4628 if(pTIHeader
->typeflags3
!= 2)
4629 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4631 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4632 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4633 typekind_desc
[pTIHeader
->typekind
],
4634 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4635 (*ppTypeInfoImpl
)->wTypeFlags
);
4637 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4639 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4641 (*ppTypeInfoImpl
)->cbAlignment
= pTITail
->cbAlignment
;
4642 (*ppTypeInfoImpl
)->cbSizeInstance
= pTITail
->cbSizeInstance
;
4643 (*ppTypeInfoImpl
)->cbSizeVft
= pTITail
->cbSizeVft
;
4645 switch(pTIHeader
->typekind
) {
4647 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4648 pTIHeader
, pTITail
);
4652 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4653 pTIHeader
, pTITail
);
4656 case TKIND_INTERFACE
:
4657 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4658 pTIHeader
, pTITail
);
4662 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4663 pTIHeader
, pTITail
);
4667 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4668 pTIHeader
, pTITail
);
4671 case TKIND_DISPATCH
:
4672 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4673 pTIHeader
, pTITail
);
4677 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4678 pTIHeader
, pTITail
);
4682 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4687 /* could get cFuncs, cVars and cImplTypes from here
4688 but we've already set those */
4689 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4705 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4708 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4709 FIXME("Somehow processed %d TypeInfos\n", i
);
4710 heap_free(pOtherTypeInfoBlks
);
4714 heap_free(pOtherTypeInfoBlks
);
4715 return &pTypeLibImpl
->ITypeLib2_iface
;
4718 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4720 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4722 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4724 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4725 IsEqualIID(riid
,&IID_ITypeLib
)||
4726 IsEqualIID(riid
,&IID_ITypeLib2
))
4728 *ppv
= &This
->ITypeLib2_iface
;
4730 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4731 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4733 *ppv
= &This
->ICreateTypeLib2_iface
;
4738 TRACE("-- Interface: E_NOINTERFACE\n");
4739 return E_NOINTERFACE
;
4742 IUnknown_AddRef((IUnknown
*)*ppv
);
4746 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4748 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4749 ULONG ref
= InterlockedIncrement(&This
->ref
);
4751 TRACE("(%p) ref=%u\n", This
, ref
);
4756 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4758 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4759 ULONG ref
= InterlockedDecrement(&This
->ref
);
4761 TRACE("(%p) ref=%u\n",This
, ref
);
4765 TLBImpLib
*pImpLib
, *pImpLibNext
;
4766 TLBRefType
*ref_type
;
4767 TLBString
*tlbstr
, *tlbstr_next
;
4768 TLBGuid
*tlbguid
, *tlbguid_next
;
4772 /* remove cache entry */
4775 TRACE("removing from cache list\n");
4776 EnterCriticalSection(&cache_section
);
4777 if(This
->entry
.next
)
4778 list_remove(&This
->entry
);
4779 LeaveCriticalSection(&cache_section
);
4780 heap_free(This
->path
);
4782 TRACE(" destroying ITypeLib(%p)\n",This
);
4784 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4785 list_remove(&tlbstr
->entry
);
4786 SysFreeString(tlbstr
->str
);
4790 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4791 list_remove(&tlbstr
->entry
);
4792 SysFreeString(tlbstr
->str
);
4796 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4797 list_remove(&tlbguid
->entry
);
4801 TLB_FreeCustData(&This
->custdata_list
);
4803 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4804 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4805 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4807 heap_free(This
->pTypeDesc
);
4809 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4811 if (pImpLib
->pImpTypeLib
)
4812 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4813 SysFreeString(pImpLib
->name
);
4815 list_remove(&pImpLib
->entry
);
4819 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4821 list_remove(&ref_type
->entry
);
4822 heap_free(ref_type
);
4825 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4826 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4827 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4829 heap_free(This
->typeinfos
);
4837 /* ITypeLib::GetTypeInfoCount
4839 * Returns the number of type descriptions in the type library
4841 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4843 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4844 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4845 return This
->TypeInfoCount
;
4848 /* ITypeLib::GetTypeInfo
4850 * retrieves the specified type description in the library.
4852 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4855 ITypeInfo
**ppTInfo
)
4857 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4859 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4862 return E_INVALIDARG
;
4864 if(index
>= This
->TypeInfoCount
)
4865 return TYPE_E_ELEMENTNOTFOUND
;
4867 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4868 ITypeInfo_AddRef(*ppTInfo
);
4874 /* ITypeLibs::GetTypeInfoType
4876 * Retrieves the type of a type description.
4878 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4883 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4885 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4888 return E_INVALIDARG
;
4890 if(index
>= This
->TypeInfoCount
)
4891 return TYPE_E_ELEMENTNOTFOUND
;
4893 *pTKind
= This
->typeinfos
[index
]->typekind
;
4898 /* ITypeLib::GetTypeInfoOfGuid
4900 * Retrieves the type description that corresponds to the specified GUID.
4903 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4906 ITypeInfo
**ppTInfo
)
4908 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4911 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4913 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4914 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4915 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4916 ITypeInfo_AddRef(*ppTInfo
);
4921 return TYPE_E_ELEMENTNOTFOUND
;
4924 /* ITypeLib::GetLibAttr
4926 * Retrieves the structure that contains the library's attributes.
4929 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4933 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4935 TRACE("(%p, %p)\n", This
, attr
);
4937 if (!attr
) return E_INVALIDARG
;
4939 *attr
= heap_alloc(sizeof(**attr
));
4940 if (!*attr
) return E_OUTOFMEMORY
;
4942 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4943 (*attr
)->lcid
= This
->set_lcid
;
4944 (*attr
)->syskind
= This
->syskind
;
4945 (*attr
)->wMajorVerNum
= This
->ver_major
;
4946 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4947 (*attr
)->wLibFlags
= This
->libflags
;
4952 /* ITypeLib::GetTypeComp
4954 * Enables a client compiler to bind to a library's types, variables,
4955 * constants, and global functions.
4958 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4960 ITypeComp
**ppTComp
)
4962 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4964 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4965 *ppTComp
= &This
->ITypeComp_iface
;
4966 ITypeComp_AddRef(*ppTComp
);
4971 /* ITypeLib::GetDocumentation
4973 * Retrieves the library's documentation string, the complete Help file name
4974 * and path, and the context identifier for the library Help topic in the Help
4977 * On a successful return all non-null BSTR pointers will have been set,
4980 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4984 BSTR
*pBstrDocString
,
4985 DWORD
*pdwHelpContext
,
4986 BSTR
*pBstrHelpFile
)
4988 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4989 HRESULT result
= E_INVALIDARG
;
4992 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4994 pBstrName
, pBstrDocString
,
4995 pdwHelpContext
, pBstrHelpFile
);
4999 /* documentation for the typelib */
5004 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
5012 if (This
->DocString
)
5014 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
5018 *pBstrDocString
= NULL
;
5022 *pdwHelpContext
= This
->dwHelpContext
;
5028 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5032 *pBstrHelpFile
= NULL
;
5039 /* for a typeinfo */
5040 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5042 if(SUCCEEDED(result
))
5044 result
= ITypeInfo_GetDocumentation(pTInfo
,
5048 pdwHelpContext
, pBstrHelpFile
);
5050 ITypeInfo_Release(pTInfo
);
5055 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5057 if (pBstrName
) SysFreeString (*pBstrName
);
5059 return STG_E_INSUFFICIENTMEMORY
;
5064 * Indicates whether a passed-in string contains the name of a type or member
5065 * described in the library.
5068 static HRESULT WINAPI
ITypeLib2_fnIsName(
5074 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5076 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5078 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5082 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5083 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5084 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5085 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5086 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5088 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5089 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5090 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5091 goto ITypeLib2_fnIsName_exit
;
5094 for(vrc
= 0; vrc
< pTInfo
->cVars
; ++vrc
){
5095 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5096 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5102 ITypeLib2_fnIsName_exit
:
5103 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5104 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5109 /* ITypeLib::FindName
5111 * Finds occurrences of a type description in a type library. This may be used
5112 * to quickly verify that a name exists in a type library.
5115 static HRESULT WINAPI
ITypeLib2_fnFindName(
5119 ITypeInfo
**ppTInfo
,
5123 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5128 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5130 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5131 return E_INVALIDARG
;
5133 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5134 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5135 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5139 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5140 memid
[count
] = MEMBERID_NIL
;
5141 goto ITypeLib2_fnFindName_exit
;
5144 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5145 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5147 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5148 memid
[count
] = func
->funcdesc
.memid
;
5149 goto ITypeLib2_fnFindName_exit
;
5153 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->cVars
, name
);
5155 memid
[count
] = var
->vardesc
.memid
;
5156 goto ITypeLib2_fnFindName_exit
;
5160 ITypeLib2_fnFindName_exit
:
5161 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5162 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5165 TRACE("found %d typeinfos\n", count
);
5172 /* ITypeLib::ReleaseTLibAttr
5174 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5177 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5179 TLIBATTR
*pTLibAttr
)
5181 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5182 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5183 heap_free(pTLibAttr
);
5186 /* ITypeLib2::GetCustData
5188 * gets the custom data
5190 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5195 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5196 TLBCustData
*pCData
;
5198 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5200 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5202 return TYPE_E_ELEMENTNOTFOUND
;
5204 VariantInit(pVarVal
);
5205 VariantCopy(pVarVal
, &pCData
->data
);
5210 /* ITypeLib2::GetLibStatistics
5212 * Returns statistics about a type library that are required for efficient
5213 * sizing of hash tables.
5216 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5218 ULONG
*pcUniqueNames
,
5219 ULONG
*pcchUniqueNames
)
5221 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5223 FIXME("(%p): stub!\n", This
);
5225 if(pcUniqueNames
) *pcUniqueNames
=1;
5226 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5230 /* ITypeLib2::GetDocumentation2
5232 * Retrieves the library's documentation string, the complete Help file name
5233 * and path, the localization context to use, and the context ID for the
5234 * library Help topic in the Help file.
5237 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5241 BSTR
*pbstrHelpString
,
5242 DWORD
*pdwHelpStringContext
,
5243 BSTR
*pbstrHelpStringDll
)
5245 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5249 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5251 /* the help string should be obtained from the helpstringdll,
5252 * using the _DLLGetDocumentation function, based on the supplied
5253 * lcid. Nice to do sometime...
5257 /* documentation for the typelib */
5259 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5260 if(pdwHelpStringContext
)
5261 *pdwHelpStringContext
=This
->dwHelpContext
;
5262 if(pbstrHelpStringDll
)
5263 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5269 /* for a typeinfo */
5270 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5272 if(SUCCEEDED(result
))
5274 ITypeInfo2
* pTInfo2
;
5275 result
= ITypeInfo_QueryInterface(pTInfo
,
5277 (LPVOID
*) &pTInfo2
);
5279 if(SUCCEEDED(result
))
5281 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5285 pdwHelpStringContext
,
5286 pbstrHelpStringDll
);
5288 ITypeInfo2_Release(pTInfo2
);
5291 ITypeInfo_Release(pTInfo
);
5297 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5299 TLBCustData
*pCData
;
5303 ct
= list_count(custdata_list
);
5305 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5306 if(!pCustData
->prgCustData
)
5307 return E_OUTOFMEMORY
;
5309 pCustData
->cCustData
= ct
;
5311 cdi
= pCustData
->prgCustData
;
5312 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5313 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5314 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5322 /* ITypeLib2::GetAllCustData
5324 * Gets all custom data items for the library.
5327 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5329 CUSTDATA
*pCustData
)
5331 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5332 TRACE("(%p)->(%p)\n", This
, pCustData
);
5333 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5336 static const ITypeLib2Vtbl tlbvt
= {
5337 ITypeLib2_fnQueryInterface
,
5339 ITypeLib2_fnRelease
,
5340 ITypeLib2_fnGetTypeInfoCount
,
5341 ITypeLib2_fnGetTypeInfo
,
5342 ITypeLib2_fnGetTypeInfoType
,
5343 ITypeLib2_fnGetTypeInfoOfGuid
,
5344 ITypeLib2_fnGetLibAttr
,
5345 ITypeLib2_fnGetTypeComp
,
5346 ITypeLib2_fnGetDocumentation
,
5348 ITypeLib2_fnFindName
,
5349 ITypeLib2_fnReleaseTLibAttr
,
5351 ITypeLib2_fnGetCustData
,
5352 ITypeLib2_fnGetLibStatistics
,
5353 ITypeLib2_fnGetDocumentation2
,
5354 ITypeLib2_fnGetAllCustData
5358 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5360 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5362 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5365 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5367 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5369 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5372 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5374 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5376 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5379 static HRESULT WINAPI
ITypeLibComp_fnBind(
5384 ITypeInfo
** ppTInfo
,
5385 DESCKIND
* pDescKind
,
5388 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5389 BOOL typemismatch
= FALSE
;
5392 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5394 *pDescKind
= DESCKIND_NONE
;
5395 pBindPtr
->lptcomp
= NULL
;
5398 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5399 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5400 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5402 /* FIXME: check wFlags here? */
5403 /* FIXME: we should use a hash table to look this info up using lHash
5404 * instead of an O(n) search */
5405 if ((pTypeInfo
->typekind
== TKIND_ENUM
) ||
5406 (pTypeInfo
->typekind
== TKIND_MODULE
))
5408 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5410 *pDescKind
= DESCKIND_TYPECOMP
;
5411 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5412 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5413 TRACE("module or enum: %s\n", debugstr_w(szName
));
5418 if ((pTypeInfo
->typekind
== TKIND_MODULE
) ||
5419 (pTypeInfo
->typekind
== TKIND_ENUM
))
5421 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5424 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5425 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5427 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5430 else if (hr
== TYPE_E_TYPEMISMATCH
)
5431 typemismatch
= TRUE
;
5434 if ((pTypeInfo
->typekind
== TKIND_COCLASS
) &&
5435 (pTypeInfo
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5437 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5439 ITypeInfo
*subtypeinfo
;
5441 DESCKIND subdesckind
;
5443 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5444 &subtypeinfo
, &subdesckind
, &subbindptr
);
5445 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5447 TYPEDESC tdesc_appobject
;
5448 const VARDESC vardesc_appobject
=
5451 NULL
, /* lpstrSchema */
5466 VAR_STATIC
/* varkind */
5469 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5470 tdesc_appobject
.vt
= VT_USERDEFINED
;
5472 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5474 /* cleanup things filled in by Bind call so we can put our
5475 * application object data in there instead */
5476 switch (subdesckind
)
5478 case DESCKIND_FUNCDESC
:
5479 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5481 case DESCKIND_VARDESC
:
5482 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5487 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5489 if (pTypeInfo
->hreftype
== -1)
5490 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5492 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5496 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5497 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5498 ITypeInfo_AddRef(*ppTInfo
);
5501 else if (hr
== TYPE_E_TYPEMISMATCH
)
5502 typemismatch
= TRUE
;
5508 TRACE("type mismatch %s\n", debugstr_w(szName
));
5509 return TYPE_E_TYPEMISMATCH
;
5513 TRACE("name not found %s\n", debugstr_w(szName
));
5518 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5522 ITypeInfo
** ppTInfo
,
5523 ITypeComp
** ppTComp
)
5525 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5526 ITypeInfoImpl
*info
;
5528 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5530 if(!szName
|| !ppTInfo
|| !ppTComp
)
5531 return E_INVALIDARG
;
5533 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5540 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5541 ITypeInfo_AddRef(*ppTInfo
);
5542 *ppTComp
= &info
->ITypeComp_iface
;
5543 ITypeComp_AddRef(*ppTComp
);
5548 static const ITypeCompVtbl tlbtcvt
=
5551 ITypeLibComp_fnQueryInterface
,
5552 ITypeLibComp_fnAddRef
,
5553 ITypeLibComp_fnRelease
,
5555 ITypeLibComp_fnBind
,
5556 ITypeLibComp_fnBindType
5559 /*================== ITypeInfo(2) Methods ===================================*/
5560 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5562 ITypeInfoImpl
*pTypeInfoImpl
;
5564 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5567 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5568 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5569 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5570 pTypeInfoImpl
->ref
= 0;
5571 pTypeInfoImpl
->hreftype
= -1;
5572 pTypeInfoImpl
->memidConstructor
= MEMBERID_NIL
;
5573 pTypeInfoImpl
->memidDestructor
= MEMBERID_NIL
;
5574 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5575 list_init(pTypeInfoImpl
->pcustdata_list
);
5577 TRACE("(%p)\n", pTypeInfoImpl
);
5578 return pTypeInfoImpl
;
5581 /* ITypeInfo::QueryInterface
5583 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5588 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5590 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5593 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5594 IsEqualIID(riid
,&IID_ITypeInfo
)||
5595 IsEqualIID(riid
,&IID_ITypeInfo2
))
5597 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5598 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5599 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5602 ITypeInfo2_AddRef(iface
);
5603 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5606 TRACE("-- Interface: E_NOINTERFACE\n");
5607 return E_NOINTERFACE
;
5610 /* ITypeInfo::AddRef
5612 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5614 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5615 ULONG ref
= InterlockedIncrement(&This
->ref
);
5617 TRACE("(%p)->ref is %u\n",This
, ref
);
5619 if (ref
== 1 /* incremented from 0 */)
5620 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5625 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5629 TRACE("destroying ITypeInfo(%p)\n",This
);
5631 for (i
= 0; i
< This
->cFuncs
; ++i
)
5634 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5635 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5637 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5638 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5639 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5640 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5642 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5643 heap_free(pFInfo
->pParamDesc
);
5644 TLB_FreeCustData(&pFInfo
->custdata_list
);
5646 heap_free(This
->funcdescs
);
5648 for(i
= 0; i
< This
->cVars
; ++i
)
5650 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5651 if (pVInfo
->vardesc_create
) {
5652 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5653 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5654 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5655 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5657 TLB_FreeCustData(&pVInfo
->custdata_list
);
5659 heap_free(This
->vardescs
);
5661 if(This
->impltypes
){
5662 for (i
= 0; i
< This
->cImplTypes
; ++i
){
5663 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5664 TLB_FreeCustData(&pImpl
->custdata_list
);
5666 heap_free(This
->impltypes
);
5669 TLB_FreeCustData(&This
->custdata_list
);
5674 /* ITypeInfo::Release
5676 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5678 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5679 ULONG ref
= InterlockedDecrement(&This
->ref
);
5681 TRACE("(%p)->(%u)\n",This
, ref
);
5685 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5686 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5687 if (not_attached_to_typelib
)
5689 /* otherwise This will be freed when typelib is freed */
5695 /* ITypeInfo::GetTypeAttr
5697 * Retrieves a TYPEATTR structure that contains the attributes of the type
5701 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5702 LPTYPEATTR
*ppTypeAttr
)
5704 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5707 TRACE("(%p)\n",This
);
5709 size
= sizeof(**ppTypeAttr
);
5710 if (This
->typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5711 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5713 *ppTypeAttr
= heap_alloc(size
);
5715 return E_OUTOFMEMORY
;
5717 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5718 (*ppTypeAttr
)->lcid
= This
->lcid
;
5719 (*ppTypeAttr
)->memidConstructor
= This
->memidConstructor
;
5720 (*ppTypeAttr
)->memidDestructor
= This
->memidDestructor
;
5721 (*ppTypeAttr
)->lpstrSchema
= This
->lpstrSchema
;
5722 (*ppTypeAttr
)->cbSizeInstance
= This
->cbSizeInstance
;
5723 (*ppTypeAttr
)->typekind
= This
->typekind
;
5724 (*ppTypeAttr
)->cFuncs
= This
->cFuncs
;
5725 (*ppTypeAttr
)->cVars
= This
->cVars
;
5726 (*ppTypeAttr
)->cImplTypes
= This
->cImplTypes
;
5727 (*ppTypeAttr
)->cbSizeVft
= This
->cbSizeVft
;
5728 (*ppTypeAttr
)->cbAlignment
= This
->cbAlignment
;
5729 (*ppTypeAttr
)->wTypeFlags
= This
->wTypeFlags
;
5730 (*ppTypeAttr
)->wMajorVerNum
= This
->wMajorVerNum
;
5731 (*ppTypeAttr
)->wMinorVerNum
= This
->wMinorVerNum
;
5732 (*ppTypeAttr
)->idldescType
= This
->idldescType
;
5734 if (This
->tdescAlias
)
5735 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5736 This
->tdescAlias
, *ppTypeAttr
+ 1);
5738 (*ppTypeAttr
)->tdescAlias
.vt
= VT_EMPTY
;
5739 (*ppTypeAttr
)->tdescAlias
.u
.lptdesc
= NULL
;
5742 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5743 /* This should include all the inherited funcs */
5744 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5745 /* This is always the size of IDispatch's vtbl */
5746 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5747 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5752 /* ITypeInfo::GetTypeComp
5754 * Retrieves the ITypeComp interface for the type description, which enables a
5755 * client compiler to bind to the type description's members.
5758 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5759 ITypeComp
* *ppTComp
)
5761 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5763 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5765 *ppTComp
= &This
->ITypeComp_iface
;
5766 ITypeComp_AddRef(*ppTComp
);
5770 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5772 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5773 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5774 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5778 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5781 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5782 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5784 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5785 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5786 *buffer
+= sizeof(PARAMDESCEX
);
5787 *pparamdescex_dest
= *pparamdescex_src
;
5788 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5789 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5790 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5791 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5794 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5798 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5800 UINT len
= SysStringLen(str
), i
;
5801 for (i
= 0; i
< len
; ++i
)
5807 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5809 if (V_VT(var
) == VT_INT
)
5810 return VariantChangeType(var
, var
, 0, VT_I4
);
5811 else if (V_VT(var
) == VT_UINT
)
5812 return VariantChangeType(var
, var
, 0, VT_UI4
);
5813 else if (V_VT(var
) == VT_BSTR
)
5814 return TLB_SanitizeBSTR(V_BSTR(var
));
5819 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5821 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5822 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5825 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5829 SIZE_T size
= sizeof(*src
);
5833 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5834 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5835 for (i
= 0; i
< src
->cParams
; i
++)
5837 size
+= sizeof(ELEMDESC
);
5838 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5841 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5842 if (!dest
) return E_OUTOFMEMORY
;
5845 if (dispinterface
) /* overwrite funckind */
5846 dest
->funckind
= FUNC_DISPATCH
;
5847 buffer
= (char *)(dest
+ 1);
5849 dest
->oVft
= dest
->oVft
& 0xFFFC;
5851 if (dest
->cScodes
) {
5852 dest
->lprgscode
= (SCODE
*)buffer
;
5853 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5854 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5856 dest
->lprgscode
= NULL
;
5858 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5861 SysFreeString((BSTR
)dest
);
5865 if (dest
->cParams
) {
5866 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5867 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5868 for (i
= 0; i
< src
->cParams
; i
++)
5870 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5876 /* undo the above actions */
5877 for (i
= i
- 1; i
>= 0; i
--)
5878 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5879 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5880 SysFreeString((BSTR
)dest
);
5884 dest
->lprgelemdescParam
= NULL
;
5886 /* special treatment for dispinterfaces: this makes functions appear
5887 * to return their [retval] value when it is really returning an
5889 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5891 if (dest
->cParams
&&
5892 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5894 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5895 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5897 ERR("elemdesc should have started with VT_PTR instead of:\n");
5899 dump_ELEMDESC(elemdesc
);
5900 return E_UNEXPECTED
;
5903 /* copy last parameter to the return value. we are using a flat
5904 * buffer so there is no danger of leaking memory in
5906 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5908 /* remove the last parameter */
5912 /* otherwise this function is made to appear to have no return
5914 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5922 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5924 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5925 if (var_desc
->varkind
== VAR_CONST
)
5926 VariantClear(var_desc
->u
.lpvarValue
);
5927 SysFreeString((BSTR
)var_desc
);
5930 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5932 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5934 if (index
>= This
->cFuncs
)
5935 return TYPE_E_ELEMENTNOTFOUND
;
5937 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5941 /* internal function to make the inherited interfaces' methods appear
5942 * part of the interface */
5943 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5944 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5946 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5948 UINT implemented_funcs
= 0;
5953 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5957 ITypeInfo
*pSubTypeInfo
;
5960 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5964 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5967 &sub_funcs
, hrefoffset
);
5968 implemented_funcs
+= sub_funcs
;
5969 ITypeInfo_Release(pSubTypeInfo
);
5972 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5976 *funcs
= implemented_funcs
+ This
->cFuncs
;
5980 if (index
< implemented_funcs
)
5981 return E_INVALIDARG
;
5982 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5986 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5988 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5991 switch (pTypeDesc
->vt
)
5993 case VT_USERDEFINED
:
5994 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5998 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
6001 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
6009 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
6012 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6013 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
6014 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
6017 /* ITypeInfo::GetFuncDesc
6019 * Retrieves the FUNCDESC structure that contains information about a
6020 * specified function.
6023 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
6024 LPFUNCDESC
*ppFuncDesc
)
6026 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6027 const FUNCDESC
*internal_funcdesc
;
6029 UINT hrefoffset
= 0;
6031 TRACE("(%p) index %d\n", This
, index
);
6034 return E_INVALIDARG
;
6036 if (This
->needs_layout
)
6037 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6039 if (This
->typekind
== TKIND_DISPATCH
)
6040 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
6041 &internal_funcdesc
, NULL
,
6044 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6045 &internal_funcdesc
);
6048 WARN("description for function %d not found\n", index
);
6052 hr
= TLB_AllocAndInitFuncDesc(
6055 This
->typekind
== TKIND_DISPATCH
);
6057 if ((This
->typekind
== TKIND_DISPATCH
) && hrefoffset
)
6058 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6060 TRACE("-- 0x%08x\n", hr
);
6064 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6068 SIZE_T size
= sizeof(*src
);
6071 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6072 if (src
->varkind
== VAR_CONST
)
6073 size
+= sizeof(VARIANT
);
6074 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6076 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6077 if (!dest
) return E_OUTOFMEMORY
;
6080 buffer
= (char *)(dest
+ 1);
6081 if (src
->lpstrSchema
)
6084 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6085 len
= strlenW(src
->lpstrSchema
);
6086 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6087 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6090 if (src
->varkind
== VAR_CONST
)
6094 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6095 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6096 buffer
+= sizeof(VARIANT
);
6097 VariantInit(dest
->u
.lpvarValue
);
6098 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6101 SysFreeString((BSTR
)dest
);
6105 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6108 if (src
->varkind
== VAR_CONST
)
6109 VariantClear(dest
->u
.lpvarValue
);
6110 SysFreeString((BSTR
)dest
);
6117 /* ITypeInfo::GetVarDesc
6119 * Retrieves a VARDESC structure that describes the specified variable.
6122 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6123 LPVARDESC
*ppVarDesc
)
6125 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6126 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6128 TRACE("(%p) index %d\n", This
, index
);
6130 if(index
>= This
->cVars
)
6131 return TYPE_E_ELEMENTNOTFOUND
;
6133 if (This
->needs_layout
)
6134 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6136 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6139 /* ITypeInfo_GetNames
6141 * Retrieves the variable with the specified member ID (or the name of the
6142 * property or method and its parameters) that correspond to the specified
6145 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6146 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6148 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6149 const TLBFuncDesc
*pFDesc
;
6150 const TLBVarDesc
*pVDesc
;
6152 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6155 return E_INVALIDARG
;
6159 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
6162 if(!cMaxNames
|| !pFDesc
->Name
)
6165 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6168 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6169 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6171 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6177 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
6180 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6185 if(This
->impltypes
&&
6186 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
6187 /* recursive search */
6190 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6191 if(SUCCEEDED(result
))
6193 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6194 ITypeInfo_Release(pTInfo
);
6197 WARN("Could not search inherited interface!\n");
6201 WARN("no names found\n");
6204 return TYPE_E_ELEMENTNOTFOUND
;
6210 /* ITypeInfo::GetRefTypeOfImplType
6212 * If a type description describes a COM class, it retrieves the type
6213 * description of the implemented interface types. For an interface,
6214 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6218 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6223 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6226 TRACE("(%p) index %d\n", This
, index
);
6227 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6231 /* only valid on dual interfaces;
6232 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6235 if (This
->wTypeFlags
& TYPEFLAG_FDUAL
)
6241 hr
= TYPE_E_ELEMENTNOTFOUND
;
6244 else if(index
== 0 && This
->typekind
== TKIND_DISPATCH
)
6246 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6247 *pRefType
= This
->pTypeLib
->dispatch_href
;
6251 if(index
>= This
->cImplTypes
)
6252 hr
= TYPE_E_ELEMENTNOTFOUND
;
6254 *pRefType
= This
->impltypes
[index
].hRef
;
6255 if(This
->typekind
== TKIND_INTERFACE
)
6263 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6265 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6271 /* ITypeInfo::GetImplTypeFlags
6273 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6274 * or base interface in a type description.
6276 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6277 UINT index
, INT
*pImplTypeFlags
)
6279 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6281 TRACE("(%p) index %d\n", This
, index
);
6284 return E_INVALIDARG
;
6286 if(This
->typekind
== TKIND_DISPATCH
&& index
== 0){
6287 *pImplTypeFlags
= 0;
6291 if(index
>= This
->cImplTypes
)
6292 return TYPE_E_ELEMENTNOTFOUND
;
6294 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6300 * Maps between member names and member IDs, and parameter names and
6303 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6304 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6306 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6307 const TLBVarDesc
*pVDesc
;
6311 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6314 /* init out parameters in case of failure */
6315 for (i
= 0; i
< cNames
; i
++)
6316 pMemId
[i
] = MEMBERID_NIL
;
6318 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
) {
6320 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6321 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6322 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6323 for(i
=1; i
< cNames
; i
++){
6324 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6325 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6327 if( j
<pFDesc
->funcdesc
.cParams
)
6330 ret
=DISP_E_UNKNOWNNAME
;
6332 TRACE("-- 0x%08x\n", ret
);
6336 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, *rgszNames
);
6339 *pMemId
= pVDesc
->vardesc
.memid
;
6342 /* not found, see if it can be found in an inherited interface */
6343 if(This
->impltypes
) {
6344 /* recursive search */
6346 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6348 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6349 ITypeInfo_Release(pTInfo
);
6352 WARN("Could not search inherited interface!\n");
6354 WARN("no names found\n");
6355 return DISP_E_UNKNOWNNAME
;
6361 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6362 __ASM_GLOBAL_FUNC( call_method
,
6364 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6365 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6366 "movl %esp,%ebp\n\t"
6367 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6369 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6371 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6372 "movl 12(%ebp),%edx\n\t"
6373 "movl %esp,%edi\n\t"
6376 "subl %edx,%edi\n\t"
6377 "andl $~15,%edi\n\t"
6378 "movl %edi,%esp\n\t"
6379 "movl 12(%ebp),%ecx\n\t"
6380 "movl 16(%ebp),%esi\n\t"
6383 "1:\tcall *8(%ebp)\n\t"
6384 "subl %esp,%edi\n\t"
6385 "movl 20(%ebp),%ecx\n\t"
6386 "movl %edi,(%ecx)\n\t"
6387 "leal -8(%ebp),%esp\n\t"
6389 __ASM_CFI(".cfi_same_value %edi\n\t")
6391 __ASM_CFI(".cfi_same_value %esi\n\t")
6393 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6394 __ASM_CFI(".cfi_same_value %ebp\n\t")
6397 /* same function but returning floating point */
6398 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6400 /* ITypeInfo::Invoke
6402 * Invokes a method, or accesses a property of an object, that implements the
6403 * interface described by the type description.
6406 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6410 if (TRACE_ON(ole
)) {
6412 TRACE("Calling %p(",func
);
6413 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6414 if (nrargs
> 30) TRACE("...");
6421 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6424 FIXME("unsupported calling convention %d\n",callconv
);
6428 TRACE("returns %08x\n",res
);
6432 #elif defined(__x86_64__)
6434 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6435 __ASM_GLOBAL_FUNC( call_method
,
6437 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6438 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6439 "movq %rsp,%rbp\n\t"
6440 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6442 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6444 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6445 "movq %rcx,%rax\n\t"
6448 "cmovgq %rdx,%rcx\n\t"
6449 "leaq 0(,%rcx,8),%rdx\n\t"
6450 "subq %rdx,%rsp\n\t"
6451 "andq $~15,%rsp\n\t"
6452 "movq %rsp,%rdi\n\t"
6455 "movq 0(%rsp),%rcx\n\t"
6456 "movq 8(%rsp),%rdx\n\t"
6457 "movq 16(%rsp),%r8\n\t"
6458 "movq 24(%rsp),%r9\n\t"
6459 "movq 0(%rsp),%xmm0\n\t"
6460 "movq 8(%rsp),%xmm1\n\t"
6461 "movq 16(%rsp),%xmm2\n\t"
6462 "movq 24(%rsp),%xmm3\n\t"
6464 "leaq -16(%rbp),%rsp\n\t"
6466 __ASM_CFI(".cfi_same_value %rdi\n\t")
6468 __ASM_CFI(".cfi_same_value %rsi\n\t")
6469 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6471 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6472 __ASM_CFI(".cfi_same_value %rbp\n\t")
6475 /* same function but returning floating point */
6476 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6478 #endif /* __x86_64__ */
6480 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6483 ITypeInfo
*tinfo2
= NULL
;
6484 TYPEATTR
*tattr
= NULL
;
6486 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6489 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6491 tdesc
->u
.hreftype
, hr
);
6494 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6497 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6498 ITypeInfo_Release(tinfo2
);
6502 switch (tattr
->typekind
)
6509 tdesc
= &tattr
->tdescAlias
;
6510 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6513 case TKIND_INTERFACE
:
6514 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6520 case TKIND_DISPATCH
:
6529 FIXME("TKIND_RECORD unhandled.\n");
6534 FIXME("TKIND_UNION unhandled.\n");
6539 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6543 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6544 ITypeInfo_Release(tinfo2
);
6548 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6552 /* enforce only one level of pointer indirection */
6553 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6555 tdesc
= tdesc
->u
.lptdesc
;
6557 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6558 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6559 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6560 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6561 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6563 VARTYPE vt_userdefined
= 0;
6564 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6565 if (tdesc
->vt
== VT_PTR
)
6567 vt_userdefined
= VT_BYREF
;
6568 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6570 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6572 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6573 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6575 *vt
|= vt_userdefined
;
6587 case VT_USERDEFINED
:
6588 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6595 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6596 hr
= DISP_E_BADVARTYPE
;
6600 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6615 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6621 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6625 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6627 ITypeInfo_Release(tinfo2
);
6631 switch(tattr
->typekind
) {
6633 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6636 case TKIND_INTERFACE
:
6637 case TKIND_DISPATCH
:
6638 *guid
= tattr
->guid
;
6642 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6643 hres
= E_UNEXPECTED
;
6646 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6647 ITypeInfo_Release(tinfo2
);
6651 /***********************************************************************
6652 * DispCallFunc (OLEAUT32.@)
6654 * Invokes a function of the specified calling convention, passing the
6655 * specified arguments and returns the result.
6658 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6659 * oVft [I] The offset in the vtable. See notes.
6660 * cc [I] Calling convention of the function to call.
6661 * vtReturn [I] The return type of the function.
6662 * cActuals [I] Number of parameters.
6663 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6664 * prgpvarg [I] The arguments to pass.
6665 * pvargResult [O] The return value of the function. Can be NULL.
6669 * Failure: HRESULT code.
6672 * The HRESULT return value of this function is not affected by the return
6673 * value of the user supplied function, which is returned in pvargResult.
6675 * If pvInstance is NULL then a non-object function is to be called and oVft
6676 * is the address of the function to call.
6678 * The cc parameter can be one of the following values:
6691 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6692 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6695 int argspos
, stack_offset
;
6700 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6701 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6702 pvargResult
, V_VT(pvargResult
));
6704 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6706 FIXME("unsupported calling convention %d\n",cc
);
6707 return E_INVALIDARG
;
6710 /* maximum size for an argument is sizeof(VARIANT) */
6711 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6713 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6717 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6718 func
= vtable
[oVft
/sizeof(void *)];
6719 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6721 else func
= (void *)oVft
;
6723 for (i
= 0; i
< cActuals
; i
++)
6725 VARIANT
*arg
= prgpvarg
[i
];
6736 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6737 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6741 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6742 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6744 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6745 args
[argspos
++] = V_BOOL(arg
);
6748 args
[argspos
++] = V_UI4(arg
);
6751 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6757 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6760 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6764 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6768 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6769 call_method( func
, argspos
, args
, &stack_offset
);
6774 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6777 WARN("invalid return type %u\n", vtReturn
);
6779 return E_INVALIDARG
;
6781 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6785 if (stack_offset
&& cc
== CC_STDCALL
)
6787 WARN( "stack pointer off by %d\n", stack_offset
);
6788 return DISP_E_BADCALLEE
;
6790 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6791 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6794 #elif defined(__x86_64__)
6800 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6801 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6802 pvargResult
, V_VT(pvargResult
));
6804 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6806 FIXME("unsupported calling convention %d\n",cc
);
6807 return E_INVALIDARG
;
6810 /* maximum size for an argument is sizeof(DWORD_PTR) */
6811 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6813 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6817 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6818 func
= vtable
[oVft
/sizeof(void *)];
6819 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6821 else func
= (void *)oVft
;
6823 for (i
= 0; i
< cActuals
; i
++)
6825 VARIANT
*arg
= prgpvarg
[i
];
6831 args
[argspos
++] = (ULONG_PTR
)arg
;
6833 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6834 args
[argspos
++] = V_BOOL(arg
);
6837 args
[argspos
++] = V_UI8(arg
);
6840 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6846 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6850 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6854 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6855 call_method( func
, argspos
, args
);
6858 WARN("invalid return type %u\n", vtReturn
);
6860 return E_INVALIDARG
;
6862 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6866 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6867 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6871 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6872 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6877 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6879 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6882 #define INVBUF_ELEMENT_SIZE \
6883 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6884 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6885 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6886 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6887 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6888 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6889 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6890 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6892 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6897 DISPPARAMS
*pDispParams
,
6898 VARIANT
*pVarResult
,
6899 EXCEPINFO
*pExcepInfo
,
6902 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6904 unsigned int var_index
;
6907 const TLBFuncDesc
*pFuncInfo
;
6910 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6911 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6914 if( This
->wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6915 return DISP_E_MEMBERNOTFOUND
;
6919 ERR("NULL pDispParams not allowed\n");
6920 return E_INVALIDARG
;
6923 dump_DispParms(pDispParams
);
6925 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6927 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6928 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6929 return E_INVALIDARG
;
6932 /* we do this instead of using GetFuncDesc since it will return a fake
6933 * FUNCDESC for dispinterfaces and we want the real function description */
6934 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
6935 pFuncInfo
= &This
->funcdescs
[fdc
];
6936 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6937 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6938 !func_restricted( &pFuncInfo
->funcdesc
))
6942 if (fdc
< This
->cFuncs
) {
6943 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6947 TRACE("invoking:\n");
6948 dump_TLBFuncDescOne(pFuncInfo
);
6951 switch (func_desc
->funckind
) {
6952 case FUNC_PUREVIRTUAL
:
6953 case FUNC_VIRTUAL
: {
6954 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6956 VARIANT retval
; /* pointer for storing byref retvals in */
6957 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6958 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6959 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6960 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6961 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6962 UINT vargs_converted
=0;
6966 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6968 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6970 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6971 hres
= DISP_E_PARAMNOTFOUND
;
6976 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6978 ERR("functions with the vararg attribute do not support named arguments\n");
6979 hres
= DISP_E_NONAMEDARGS
;
6983 for (i
= 0; i
< func_desc
->cParams
; i
++)
6985 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6986 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6991 TRACE("changing args\n");
6992 for (i
= 0; i
< func_desc
->cParams
; i
++)
6994 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6995 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6996 VARIANTARG
*src_arg
;
6998 if (wParamFlags
& PARAMFLAG_FLCID
)
7001 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7003 V_I4(arg
) = This
->pTypeLib
->lcid
;
7012 for (j
= 0; j
< cNamedArgs
; j
++)
7013 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7015 src_arg
= &pDispParams
->rgvarg
[j
];
7020 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7022 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7026 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7028 /* under most conditions the caller is not allowed to
7029 * pass in a dispparam arg in the index of what would be
7030 * the retval parameter. however, there is an exception
7031 * where the extra parameter is used in an extra
7032 * IDispatch::Invoke below */
7033 if ((i
< pDispParams
->cArgs
) &&
7034 ((func_desc
->cParams
!= 1) || !pVarResult
||
7035 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7037 hres
= DISP_E_BADPARAMCOUNT
;
7041 /* note: this check is placed so that if the caller passes
7042 * in a VARIANTARG for the retval we just ignore it, like
7044 if (i
== func_desc
->cParams
- 1)
7047 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7048 memset(arg
, 0, sizeof(*arg
));
7049 V_VT(arg
) = rgvt
[i
];
7050 memset(&retval
, 0, sizeof(retval
));
7051 V_BYREF(arg
) = &retval
;
7055 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7056 hres
= E_UNEXPECTED
;
7062 TRACE("%s\n", debugstr_variant(src_arg
));
7064 if(rgvt
[i
]!=V_VT(src_arg
))
7066 if (rgvt
[i
] == VT_VARIANT
)
7067 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7068 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7070 if (rgvt
[i
] == V_VT(src_arg
))
7071 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7074 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7075 if (wParamFlags
& PARAMFLAG_FIN
)
7076 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7077 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7079 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7081 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7084 SAFEARRAYBOUND bound
;
7088 bound
.cElements
= pDispParams
->cArgs
-i
;
7089 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7091 ERR("SafeArrayCreate failed\n");
7094 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7097 ERR("SafeArrayAccessData failed with %x\n", hres
);
7098 SafeArrayDestroy(a
);
7101 for (j
= 0; j
< bound
.cElements
; j
++)
7102 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7103 hres
= SafeArrayUnaccessData(a
);
7106 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7107 SafeArrayDestroy(a
);
7110 if (rgvt
[i
] & VT_BYREF
)
7111 V_BYREF(&rgvarg
[i
]) = &a
;
7113 V_ARRAY(&rgvarg
[i
]) = a
;
7114 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7116 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7118 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7119 if (wParamFlags
& PARAMFLAG_FIN
)
7120 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7122 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7123 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7124 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7126 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7128 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7129 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7133 /* FIXME: this doesn't work for VT_BYREF arguments if
7134 * they are not the same type as in the paramdesc */
7135 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7136 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7137 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7142 ERR("failed to convert param %d to %s from %s\n", i
,
7143 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7146 prgpvarg
[i
] = &rgvarg
[i
];
7150 prgpvarg
[i
] = src_arg
;
7153 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7154 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7155 && V_UNKNOWN(prgpvarg
[i
])) {
7156 IUnknown
*userdefined_iface
;
7159 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7163 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7165 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7169 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7170 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7173 else if (wParamFlags
& PARAMFLAG_FOPT
)
7176 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7177 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7179 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7185 VARIANTARG
*missing_arg
;
7186 /* if the function wants a pointer to a variant then
7187 * set that up, otherwise just pass the VT_ERROR in
7188 * the argument by value */
7189 if (rgvt
[i
] & VT_BYREF
)
7191 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7192 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7193 V_VARIANTREF(arg
) = missing_arg
;
7197 V_VT(missing_arg
) = VT_ERROR
;
7198 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7203 hres
= DISP_E_BADPARAMCOUNT
;
7207 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7209 /* VT_VOID is a special case for return types, so it is not
7210 * handled in the general function */
7211 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7212 V_VT(&varresult
) = VT_EMPTY
;
7215 V_VT(&varresult
) = 0;
7216 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7217 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7220 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7221 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7222 prgpvarg
, &varresult
);
7224 vargs_converted
= 0;
7226 for (i
= 0; i
< func_desc
->cParams
; i
++)
7228 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7229 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7231 if (wParamFlags
& PARAMFLAG_FLCID
)
7233 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7235 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7239 VariantInit(pVarResult
);
7240 /* deref return value */
7241 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7244 VARIANT_ClearInd(prgpvarg
[i
]);
7246 else if (vargs_converted
< pDispParams
->cArgs
)
7248 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7249 if (wParamFlags
& PARAMFLAG_FOUT
)
7251 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7253 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7257 ERR("failed to convert param %d to vt %d\n", i
,
7258 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7263 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7264 func_desc
->cParamsOpt
< 0 &&
7265 i
== func_desc
->cParams
-1)
7267 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7270 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7273 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7276 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7279 ERR("SafeArrayAccessData failed with %x\n", hres
);
7282 for (j
= 0; j
<= ubound
; j
++)
7283 VariantClear(&v
[j
]);
7284 hres
= SafeArrayUnaccessData(a
);
7287 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7291 VariantClear(&rgvarg
[i
]);
7294 else if (wParamFlags
& PARAMFLAG_FOPT
)
7296 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7297 VariantClear(&rgvarg
[i
]);
7300 VariantClear(&missing_arg
[i
]);
7303 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7305 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7306 hres
= DISP_E_EXCEPTION
;
7309 IErrorInfo
*pErrorInfo
;
7310 pExcepInfo
->scode
= V_ERROR(&varresult
);
7311 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7313 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7314 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7315 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7316 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7318 IErrorInfo_Release(pErrorInfo
);
7322 if (V_VT(&varresult
) != VT_ERROR
)
7324 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7328 VariantClear(pVarResult
);
7329 *pVarResult
= varresult
;
7332 VariantClear(&varresult
);
7335 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7336 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7337 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7338 (pDispParams
->cArgs
!= 0))
7340 if (V_VT(pVarResult
) == VT_DISPATCH
)
7342 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7343 /* Note: not VariantClear; we still need the dispatch
7344 * pointer to be valid */
7345 VariantInit(pVarResult
);
7346 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7347 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7348 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7349 IDispatch_Release(pDispatch
);
7353 VariantClear(pVarResult
);
7354 hres
= DISP_E_NOTACOLLECTION
;
7362 case FUNC_DISPATCH
: {
7365 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7366 if (SUCCEEDED(hres
)) {
7367 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7368 hres
= IDispatch_Invoke(
7369 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7370 pVarResult
,pExcepInfo
,pArgErr
7373 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7374 IDispatch_Release(disp
);
7376 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7380 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7385 TRACE("-- 0x%08x\n", hres
);
7388 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7391 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7392 if(FAILED(hres
)) return hres
;
7394 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7395 dump_VARDESC(var_desc
);
7396 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7400 /* not found, look for it in inherited interfaces */
7401 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7402 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7403 if(This
->impltypes
) {
7404 /* recursive search */
7406 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7407 if(SUCCEEDED(hres
)){
7408 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7409 ITypeInfo_Release(pTInfo
);
7412 WARN("Could not search inherited interface!\n");
7415 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7416 return DISP_E_MEMBERNOTFOUND
;
7419 /* ITypeInfo::GetDocumentation
7421 * Retrieves the documentation string, the complete Help file name and path,
7422 * and the context ID for the Help topic for a specified type description.
7424 * (Can be tested by the Visual Basic Editor in Word for instance.)
7426 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7427 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7428 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7430 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7431 const TLBFuncDesc
*pFDesc
;
7432 const TLBVarDesc
*pVDesc
;
7433 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7434 " HelpContext(%p) HelpFile(%p)\n",
7435 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7436 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7438 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7440 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7442 *pdwHelpContext
=This
->dwHelpContext
;
7444 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7446 }else {/* for a member */
7447 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7450 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7452 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7454 *pdwHelpContext
=pFDesc
->helpcontext
;
7456 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7459 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7462 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7464 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7466 *pdwHelpContext
=pVDesc
->HelpContext
;
7468 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7473 if(This
->impltypes
&&
7474 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
7475 /* recursive search */
7478 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7479 if(SUCCEEDED(result
)) {
7480 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7481 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7482 ITypeInfo_Release(pTInfo
);
7485 WARN("Could not search inherited interface!\n");
7488 WARN("member %d not found\n", memid
);
7489 return TYPE_E_ELEMENTNOTFOUND
;
7492 /* ITypeInfo::GetDllEntry
7494 * Retrieves a description or specification of an entry point for a function
7497 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7498 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7501 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7502 const TLBFuncDesc
*pFDesc
;
7504 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7506 if (pBstrDllName
) *pBstrDllName
= NULL
;
7507 if (pBstrName
) *pBstrName
= NULL
;
7508 if (pwOrdinal
) *pwOrdinal
= 0;
7510 if (This
->typekind
!= TKIND_MODULE
)
7511 return TYPE_E_BADMODULEKIND
;
7513 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7515 dump_TypeInfo(This
);
7517 dump_TLBFuncDescOne(pFDesc
);
7520 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7522 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7524 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7532 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7535 return TYPE_E_ELEMENTNOTFOUND
;
7538 /* internal function to make the inherited interfaces' methods appear
7539 * part of the interface */
7540 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7541 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7543 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7546 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7548 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7550 ITypeInfo
*pSubTypeInfo
;
7552 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7556 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7558 ITypeInfo_Release(pSubTypeInfo
);
7562 *hRefType
-= DISPATCH_HREF_OFFSET
;
7564 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7565 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7570 struct search_res_tlb_params
7576 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7578 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7579 static const WCHAR formatW
[] = {'\\','%','d',0};
7580 WCHAR szPath
[MAX_PATH
+1];
7581 ITypeLib
*pTLib
= NULL
;
7585 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7588 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7591 if (snprintfW(szPath
+ len
, sizeof(szPath
)/sizeof(WCHAR
) - len
, formatW
, LOWORD(lpszName
)) < 0)
7594 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7597 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7598 if (IsEqualGUID(params
->guid
, impl
->guid
))
7600 params
->pTLib
= pTLib
;
7601 return FALSE
; /* stop enumeration */
7603 ITypeLib_Release(pTLib
);
7609 /* ITypeInfo::GetRefTypeInfo
7611 * If a type description references other type descriptions, it retrieves
7612 * the referenced type descriptions.
7614 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7617 ITypeInfo
**ppTInfo
)
7619 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7620 HRESULT result
= E_FAIL
;
7623 return E_INVALIDARG
;
7625 if ((INT
)hRefType
< 0) {
7626 ITypeInfoImpl
*pTypeInfoImpl
;
7628 if (!(This
->wTypeFlags
& TYPEFLAG_FDUAL
) ||
7629 !(This
->typekind
== TKIND_INTERFACE
||
7630 This
->typekind
== TKIND_DISPATCH
))
7631 return TYPE_E_ELEMENTNOTFOUND
;
7633 /* when we meet a DUAL typeinfo, we must create the alternate
7636 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7638 *pTypeInfoImpl
= *This
;
7639 pTypeInfoImpl
->ref
= 0;
7640 list_init(&pTypeInfoImpl
->custdata_list
);
7642 if (This
->typekind
== TKIND_INTERFACE
)
7643 pTypeInfoImpl
->typekind
= TKIND_DISPATCH
;
7645 pTypeInfoImpl
->typekind
= TKIND_INTERFACE
;
7647 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7648 /* the AddRef implicitly adds a reference to the parent typelib, which
7649 * stops the copied data from being destroyed until the new typeinfo's
7650 * refcount goes to zero, but we need to signal to the new instance to
7651 * not free its data structures when it is destroyed */
7652 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7654 ITypeInfo_AddRef(*ppTInfo
);
7657 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7658 (This
->typekind
== TKIND_DISPATCH
))
7660 HREFTYPE href_dispatch
= hRefType
;
7661 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7663 TLBRefType
*ref_type
;
7664 ITypeLib
*pTLib
= NULL
;
7667 if(!(hRefType
& 0x1)){
7668 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7670 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7673 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7674 ITypeInfo_AddRef(*ppTInfo
);
7680 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7682 if(ref_type
->reference
== (hRefType
& (~0x3)))
7685 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7687 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7691 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7693 TRACE("internal reference\n");
7694 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7696 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7697 TRACE("typeinfo in imported typelib that is already loaded\n");
7698 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7699 ITypeLib_AddRef(pTLib
);
7702 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
7703 struct search_res_tlb_params params
;
7706 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7708 /* Search in resource table */
7709 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
7710 params
.pTLib
= NULL
;
7711 EnumResourceNamesW(NULL
, TYPELIBW
, search_res_tlb
, (LONG_PTR
)¶ms
);
7712 pTLib
= params
.pTLib
;
7717 /* Search on disk */
7718 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7719 ref_type
->pImpTLInfo
->wVersionMajor
,
7720 ref_type
->pImpTLInfo
->wVersionMinor
,
7721 This
->pTypeLib
->syskind
,
7722 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7724 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7726 result
= LoadTypeLib(libnam
, &pTLib
);
7727 SysFreeString(libnam
);
7730 if(SUCCEEDED(result
)) {
7731 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7732 ITypeLib_AddRef(pTLib
);
7736 if(SUCCEEDED(result
)) {
7737 if(ref_type
->index
== TLB_REF_USE_GUID
)
7738 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7740 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7743 ITypeLib_Release(pTLib
);
7747 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7748 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7752 /* ITypeInfo::AddressOfMember
7754 * Retrieves the addresses of static functions or variables, such as those
7757 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7758 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7760 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7766 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7768 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7772 module
= LoadLibraryW(dll
);
7775 ERR("couldn't load %s\n", debugstr_w(dll
));
7777 SysFreeString(entry
);
7778 return STG_E_FILENOTFOUND
;
7780 /* FIXME: store library somewhere where we can free it */
7785 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7786 entryA
= heap_alloc(len
);
7787 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7789 *ppv
= GetProcAddress(module
, entryA
);
7791 ERR("function not found %s\n", debugstr_a(entryA
));
7797 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7799 ERR("function not found %d\n", ordinal
);
7803 SysFreeString(entry
);
7806 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7811 /* ITypeInfo::CreateInstance
7813 * Creates a new instance of a type that describes a component object class
7816 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7817 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7819 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7823 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7829 WARN("Not able to aggregate\n");
7830 return CLASS_E_NOAGGREGATION
;
7833 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7834 if(FAILED(hr
)) return hr
;
7836 if(pTA
->typekind
!= TKIND_COCLASS
)
7838 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7844 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7847 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7848 TRACE("GetActiveObject rets %08x\n", hr
);
7851 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7852 IUnknown_Release(pUnk
);
7857 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7858 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7862 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7866 /* ITypeInfo::GetMops
7868 * Retrieves marshalling information.
7870 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7873 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7874 FIXME("(%p %d) stub!\n", This
, memid
);
7879 /* ITypeInfo::GetContainingTypeLib
7881 * Retrieves the containing type library and the index of the type description
7882 * within that type library.
7884 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7885 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7887 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7889 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7891 *pIndex
=This
->index
;
7892 TRACE("returning pIndex=%d\n", *pIndex
);
7896 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7897 ITypeLib_AddRef(*ppTLib
);
7898 TRACE("returning ppTLib=%p\n", *ppTLib
);
7904 /* ITypeInfo::ReleaseTypeAttr
7906 * Releases a TYPEATTR previously returned by Get
7909 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7910 TYPEATTR
* pTypeAttr
)
7912 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7913 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7914 heap_free(pTypeAttr
);
7917 /* ITypeInfo::ReleaseFuncDesc
7919 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7921 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7923 FUNCDESC
*pFuncDesc
)
7925 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7928 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7930 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7931 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7932 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7934 SysFreeString((BSTR
)pFuncDesc
);
7937 /* ITypeInfo::ReleaseVarDesc
7939 * Releases a VARDESC previously returned by GetVarDesc.
7941 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7944 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7945 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7947 TLB_FreeVarDesc(pVarDesc
);
7950 /* ITypeInfo2::GetTypeKind
7952 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7955 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7956 TYPEKIND
*pTypeKind
)
7958 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7959 *pTypeKind
=This
->typekind
;
7960 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7964 /* ITypeInfo2::GetTypeFlags
7966 * Returns the type flags without any allocations. This returns a DWORD type
7967 * flag, which expands the type flags without growing the TYPEATTR (type
7971 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7973 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7974 *pTypeFlags
=This
->wTypeFlags
;
7975 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7979 /* ITypeInfo2::GetFuncIndexOfMemId
7980 * Binds to a specific member based on a known DISPID, where the member name
7981 * is not known (for example, when binding to a default member).
7984 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7985 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7987 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7991 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
7992 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7993 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7996 if(fdc
< This
->cFuncs
) {
8000 result
= TYPE_E_ELEMENTNOTFOUND
;
8002 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
8003 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8007 /* TypeInfo2::GetVarIndexOfMemId
8009 * Binds to a specific member based on a known DISPID, where the member name
8010 * is not known (for example, when binding to a default member).
8013 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8014 MEMBERID memid
, UINT
*pVarIndex
)
8016 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8017 TLBVarDesc
*pVarInfo
;
8019 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8021 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8023 return TYPE_E_ELEMENTNOTFOUND
;
8025 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8030 /* ITypeInfo2::GetCustData
8032 * Gets the custom data
8034 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8039 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8040 TLBCustData
*pCData
;
8042 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8044 if(!guid
|| !pVarVal
)
8045 return E_INVALIDARG
;
8047 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8049 VariantInit( pVarVal
);
8051 VariantCopy( pVarVal
, &pCData
->data
);
8053 VariantClear( pVarVal
);
8057 /* ITypeInfo2::GetFuncCustData
8059 * Gets the custom data
8061 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8067 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8068 TLBCustData
*pCData
;
8069 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8071 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8073 if(index
>= This
->cFuncs
)
8074 return TYPE_E_ELEMENTNOTFOUND
;
8076 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8078 return TYPE_E_ELEMENTNOTFOUND
;
8080 VariantInit(pVarVal
);
8081 VariantCopy(pVarVal
, &pCData
->data
);
8086 /* ITypeInfo2::GetParamCustData
8088 * Gets the custom data
8090 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8097 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8098 TLBCustData
*pCData
;
8099 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8101 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8102 debugstr_guid(guid
), pVarVal
);
8104 if(indexFunc
>= This
->cFuncs
)
8105 return TYPE_E_ELEMENTNOTFOUND
;
8107 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8108 return TYPE_E_ELEMENTNOTFOUND
;
8110 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8112 return TYPE_E_ELEMENTNOTFOUND
;
8114 VariantInit(pVarVal
);
8115 VariantCopy(pVarVal
, &pCData
->data
);
8120 /* ITypeInfo2::GetVarCustData
8122 * Gets the custom data
8124 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8130 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8131 TLBCustData
*pCData
;
8132 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8134 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8136 if(index
>= This
->cVars
)
8137 return TYPE_E_ELEMENTNOTFOUND
;
8139 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8141 return TYPE_E_ELEMENTNOTFOUND
;
8143 VariantInit(pVarVal
);
8144 VariantCopy(pVarVal
, &pCData
->data
);
8149 /* ITypeInfo2::GetImplCustData
8151 * Gets the custom data
8153 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8159 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8160 TLBCustData
*pCData
;
8161 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8163 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8165 if(index
>= This
->cImplTypes
)
8166 return TYPE_E_ELEMENTNOTFOUND
;
8168 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8170 return TYPE_E_ELEMENTNOTFOUND
;
8172 VariantInit(pVarVal
);
8173 VariantCopy(pVarVal
, &pCData
->data
);
8178 /* ITypeInfo2::GetDocumentation2
8180 * Retrieves the documentation string, the complete Help file name and path,
8181 * the localization context to use, and the context ID for the library Help
8182 * topic in the Help file.
8185 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8189 BSTR
*pbstrHelpString
,
8190 DWORD
*pdwHelpStringContext
,
8191 BSTR
*pbstrHelpStringDll
)
8193 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8194 const TLBFuncDesc
*pFDesc
;
8195 const TLBVarDesc
*pVDesc
;
8196 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8197 "HelpStringContext(%p) HelpStringDll(%p)\n",
8198 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8199 pbstrHelpStringDll
);
8200 /* the help string should be obtained from the helpstringdll,
8201 * using the _DLLGetDocumentation function, based on the supplied
8202 * lcid. Nice to do sometime...
8204 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8206 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8207 if(pdwHelpStringContext
)
8208 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8209 if(pbstrHelpStringDll
)
8210 *pbstrHelpStringDll
=
8211 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8213 }else {/* for a member */
8214 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
8217 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8218 if(pdwHelpStringContext
)
8219 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8220 if(pbstrHelpStringDll
)
8221 *pbstrHelpStringDll
=
8222 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8225 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8228 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8229 if(pdwHelpStringContext
)
8230 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8231 if(pbstrHelpStringDll
)
8232 *pbstrHelpStringDll
=
8233 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8237 return TYPE_E_ELEMENTNOTFOUND
;
8240 /* ITypeInfo2::GetAllCustData
8242 * Gets all custom data items for the Type info.
8245 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8247 CUSTDATA
*pCustData
)
8249 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8251 TRACE("%p %p\n", This
, pCustData
);
8253 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8256 /* ITypeInfo2::GetAllFuncCustData
8258 * Gets all custom data items for the specified Function
8261 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8264 CUSTDATA
*pCustData
)
8266 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8267 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8269 TRACE("%p %u %p\n", This
, index
, pCustData
);
8271 if(index
>= This
->cFuncs
)
8272 return TYPE_E_ELEMENTNOTFOUND
;
8274 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8277 /* ITypeInfo2::GetAllParamCustData
8279 * Gets all custom data items for the Functions
8282 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8283 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8285 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8286 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8288 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8290 if(indexFunc
>= This
->cFuncs
)
8291 return TYPE_E_ELEMENTNOTFOUND
;
8293 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8294 return TYPE_E_ELEMENTNOTFOUND
;
8296 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8299 /* ITypeInfo2::GetAllVarCustData
8301 * Gets all custom data items for the specified Variable
8304 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8305 UINT index
, CUSTDATA
*pCustData
)
8307 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8308 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8310 TRACE("%p %u %p\n", This
, index
, pCustData
);
8312 if(index
>= This
->cVars
)
8313 return TYPE_E_ELEMENTNOTFOUND
;
8315 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8318 /* ITypeInfo2::GetAllImplCustData
8320 * Gets all custom data items for the specified implementation type
8323 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8326 CUSTDATA
*pCustData
)
8328 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8329 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8331 TRACE("%p %u %p\n", This
, index
, pCustData
);
8333 if(index
>= This
->cImplTypes
)
8334 return TYPE_E_ELEMENTNOTFOUND
;
8336 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8339 static const ITypeInfo2Vtbl tinfvt
=
8342 ITypeInfo_fnQueryInterface
,
8344 ITypeInfo_fnRelease
,
8346 ITypeInfo_fnGetTypeAttr
,
8347 ITypeInfo_fnGetTypeComp
,
8348 ITypeInfo_fnGetFuncDesc
,
8349 ITypeInfo_fnGetVarDesc
,
8350 ITypeInfo_fnGetNames
,
8351 ITypeInfo_fnGetRefTypeOfImplType
,
8352 ITypeInfo_fnGetImplTypeFlags
,
8353 ITypeInfo_fnGetIDsOfNames
,
8355 ITypeInfo_fnGetDocumentation
,
8356 ITypeInfo_fnGetDllEntry
,
8357 ITypeInfo_fnGetRefTypeInfo
,
8358 ITypeInfo_fnAddressOfMember
,
8359 ITypeInfo_fnCreateInstance
,
8360 ITypeInfo_fnGetMops
,
8361 ITypeInfo_fnGetContainingTypeLib
,
8362 ITypeInfo_fnReleaseTypeAttr
,
8363 ITypeInfo_fnReleaseFuncDesc
,
8364 ITypeInfo_fnReleaseVarDesc
,
8366 ITypeInfo2_fnGetTypeKind
,
8367 ITypeInfo2_fnGetTypeFlags
,
8368 ITypeInfo2_fnGetFuncIndexOfMemId
,
8369 ITypeInfo2_fnGetVarIndexOfMemId
,
8370 ITypeInfo2_fnGetCustData
,
8371 ITypeInfo2_fnGetFuncCustData
,
8372 ITypeInfo2_fnGetParamCustData
,
8373 ITypeInfo2_fnGetVarCustData
,
8374 ITypeInfo2_fnGetImplTypeCustData
,
8375 ITypeInfo2_fnGetDocumentation2
,
8376 ITypeInfo2_fnGetAllCustData
,
8377 ITypeInfo2_fnGetAllFuncCustData
,
8378 ITypeInfo2_fnGetAllParamCustData
,
8379 ITypeInfo2_fnGetAllVarCustData
,
8380 ITypeInfo2_fnGetAllImplTypeCustData
,
8383 /******************************************************************************
8384 * CreateDispTypeInfo [OLEAUT32.31]
8386 * Build type information for an object so it can be called through an
8387 * IDispatch interface.
8390 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8391 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8394 * This call allows an objects methods to be accessed through IDispatch, by
8395 * building an ITypeInfo object that IDispatch can use to call through.
8397 HRESULT WINAPI
CreateDispTypeInfo(
8398 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8399 LCID lcid
, /* [I] Locale Id */
8400 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8402 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8403 ITypeLibImpl
*pTypeLibImpl
;
8404 unsigned int param
, func
;
8405 TLBFuncDesc
*pFuncDesc
;
8409 pTypeLibImpl
= TypeLibImpl_Constructor();
8410 if (!pTypeLibImpl
) return E_FAIL
;
8412 pTypeLibImpl
->TypeInfoCount
= 2;
8413 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8415 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8416 pTIIface
->pTypeLib
= pTypeLibImpl
;
8417 pTIIface
->index
= 0;
8418 pTIIface
->Name
= NULL
;
8419 pTIIface
->dwHelpContext
= -1;
8420 pTIIface
->guid
= NULL
;
8421 pTIIface
->lcid
= lcid
;
8422 pTIIface
->typekind
= TKIND_INTERFACE
;
8423 pTIIface
->wMajorVerNum
= 0;
8424 pTIIface
->wMinorVerNum
= 0;
8425 pTIIface
->cbAlignment
= 2;
8426 pTIIface
->cbSizeInstance
= -1;
8427 pTIIface
->cbSizeVft
= -1;
8428 pTIIface
->cFuncs
= 0;
8429 pTIIface
->cImplTypes
= 0;
8430 pTIIface
->cVars
= 0;
8431 pTIIface
->wTypeFlags
= 0;
8432 pTIIface
->hreftype
= 0;
8434 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8435 pFuncDesc
= pTIIface
->funcdescs
;
8436 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8437 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8438 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8439 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8440 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8441 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8442 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8443 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8444 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8445 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8446 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8447 pFuncDesc
->funcdesc
.cScodes
= 0;
8448 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8449 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8450 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8451 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8452 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8453 md
->cArgs
* sizeof(ELEMDESC
));
8454 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8455 for(param
= 0; param
< md
->cArgs
; param
++) {
8456 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8457 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8459 pFuncDesc
->helpcontext
= 0;
8460 pFuncDesc
->HelpStringContext
= 0;
8461 pFuncDesc
->HelpString
= NULL
;
8462 pFuncDesc
->Entry
= NULL
;
8463 list_init(&pFuncDesc
->custdata_list
);
8468 dump_TypeInfo(pTIIface
);
8470 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8471 pTIClass
->pTypeLib
= pTypeLibImpl
;
8472 pTIClass
->index
= 1;
8473 pTIClass
->Name
= NULL
;
8474 pTIClass
->dwHelpContext
= -1;
8475 pTIClass
->guid
= NULL
;
8476 pTIClass
->lcid
= lcid
;
8477 pTIClass
->typekind
= TKIND_COCLASS
;
8478 pTIClass
->wMajorVerNum
= 0;
8479 pTIClass
->wMinorVerNum
= 0;
8480 pTIClass
->cbAlignment
= 2;
8481 pTIClass
->cbSizeInstance
= -1;
8482 pTIClass
->cbSizeVft
= -1;
8483 pTIClass
->cFuncs
= 0;
8484 pTIClass
->cImplTypes
= 1;
8485 pTIClass
->cVars
= 0;
8486 pTIClass
->wTypeFlags
= 0;
8487 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8489 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8491 ref
= heap_alloc_zero(sizeof(*ref
));
8492 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8493 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8495 dump_TypeInfo(pTIClass
);
8497 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8499 ITypeInfo_AddRef(*pptinfo
);
8500 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8506 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8508 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8510 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8513 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8515 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8517 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8520 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8522 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8524 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8527 static HRESULT WINAPI
ITypeComp_fnBind(
8532 ITypeInfo
** ppTInfo
,
8533 DESCKIND
* pDescKind
,
8536 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8537 const TLBFuncDesc
*pFDesc
;
8538 const TLBVarDesc
*pVDesc
;
8539 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8542 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8544 *pDescKind
= DESCKIND_NONE
;
8545 pBindPtr
->lpfuncdesc
= NULL
;
8548 for(fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8549 pFDesc
= &This
->funcdescs
[fdc
];
8550 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8551 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8554 /* name found, but wrong flags */
8555 hr
= TYPE_E_TYPEMISMATCH
;
8559 if (fdc
< This
->cFuncs
)
8561 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8563 &pBindPtr
->lpfuncdesc
,
8564 This
->typekind
== TKIND_DISPATCH
);
8567 *pDescKind
= DESCKIND_FUNCDESC
;
8568 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8569 ITypeInfo_AddRef(*ppTInfo
);
8572 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, szName
);
8574 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8577 *pDescKind
= DESCKIND_VARDESC
;
8578 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8579 ITypeInfo_AddRef(*ppTInfo
);
8584 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8585 /* recursive search */
8589 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8592 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8593 ITypeInfo_Release(pTInfo
);
8597 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8598 ITypeComp_Release(pTComp
);
8599 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8600 This
->typekind
== TKIND_DISPATCH
)
8602 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8603 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8604 SysFreeString((BSTR
)tmp
);
8608 WARN("Could not search inherited interface!\n");
8610 if (hr
== DISP_E_MEMBERNOTFOUND
)
8612 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8616 static HRESULT WINAPI
ITypeComp_fnBindType(
8620 ITypeInfo
** ppTInfo
,
8621 ITypeComp
** ppTComp
)
8623 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8625 /* strange behaviour (does nothing) but like the
8628 if (!ppTInfo
|| !ppTComp
)
8637 static const ITypeCompVtbl tcompvt
=
8640 ITypeComp_fnQueryInterface
,
8642 ITypeComp_fnRelease
,
8645 ITypeComp_fnBindType
8648 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8649 ICreateTypeLib2
** ppctlib
)
8654 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8656 if (!szFile
) return E_INVALIDARG
;
8658 This
= TypeLibImpl_Constructor();
8660 return E_OUTOFMEMORY
;
8662 This
->lcid
= GetSystemDefaultLCID();
8663 This
->syskind
= syskind
;
8664 This
->ptr_size
= get_ptr_size(syskind
);
8666 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8668 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8669 return E_OUTOFMEMORY
;
8671 lstrcpyW(This
->path
, szFile
);
8673 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8674 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8678 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8679 REFIID riid
, void **object
)
8681 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8683 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8686 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8688 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8690 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8693 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8695 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8697 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8700 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8701 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8703 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8704 ITypeInfoImpl
*info
;
8707 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8709 if (!ctinfo
|| !name
)
8710 return E_INVALIDARG
;
8712 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8714 return TYPE_E_NAMECONFLICT
;
8716 if (This
->typeinfos
)
8717 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8718 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8720 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8722 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8724 info
->pTypeLib
= This
;
8725 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8726 info
->index
= This
->TypeInfoCount
;
8727 info
->typekind
= kind
;
8728 info
->cbAlignment
= 4;
8730 switch(info
->typekind
) {
8732 case TKIND_INTERFACE
:
8733 case TKIND_DISPATCH
:
8735 info
->cbSizeInstance
= This
->ptr_size
;
8739 info
->cbSizeInstance
= 0;
8742 info
->cbSizeInstance
= 2;
8745 info
->cbSizeInstance
= -0x75;
8748 FIXME("unrecognized typekind %d\n", info
->typekind
);
8749 info
->cbSizeInstance
= 0xdeadbeef;
8753 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8754 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8756 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8760 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8762 ++This
->TypeInfoCount
;
8767 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8770 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8772 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8775 return E_INVALIDARG
;
8777 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8782 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8783 WORD majorVerNum
, WORD minorVerNum
)
8785 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8787 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8789 This
->ver_major
= majorVerNum
;
8790 This
->ver_minor
= minorVerNum
;
8795 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8798 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8800 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8802 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8807 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8810 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8812 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8815 return E_INVALIDARG
;
8817 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8822 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8823 LPOLESTR helpFileName
)
8825 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8827 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8830 return E_INVALIDARG
;
8832 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8837 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8840 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8842 TRACE("%p %d\n", This
, helpContext
);
8844 This
->dwHelpContext
= helpContext
;
8849 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8852 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8854 TRACE("%p %x\n", This
, lcid
);
8856 This
->set_lcid
= lcid
;
8861 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8864 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8866 TRACE("%p %x\n", This
, libFlags
);
8868 This
->libflags
= libFlags
;
8873 typedef struct tagWMSFT_SegContents
{
8876 } WMSFT_SegContents
;
8878 typedef struct tagWMSFT_TLBFile
{
8880 WMSFT_SegContents typeinfo_seg
;
8881 WMSFT_SegContents impfile_seg
;
8882 WMSFT_SegContents impinfo_seg
;
8883 WMSFT_SegContents ref_seg
;
8884 WMSFT_SegContents guidhash_seg
;
8885 WMSFT_SegContents guid_seg
;
8886 WMSFT_SegContents namehash_seg
;
8887 WMSFT_SegContents name_seg
;
8888 WMSFT_SegContents string_seg
;
8889 WMSFT_SegContents typdesc_seg
;
8890 WMSFT_SegContents arraydesc_seg
;
8891 WMSFT_SegContents custdata_seg
;
8892 WMSFT_SegContents cdguids_seg
;
8894 WMSFT_SegContents aux_seg
;
8897 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8898 WMSFT_TLBFile
*file
)
8904 file
->string_seg
.len
= 0;
8905 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8908 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8910 return E_UNEXPECTED
;
8912 size
+= sizeof(INT16
);
8914 size
= (size
+ 4) & ~0x3;
8918 file
->string_seg
.len
+= size
;
8920 /* temporarily use str->offset to store the length of the aligned,
8921 * converted string */
8925 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8928 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8931 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8932 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8934 heap_free(file
->string_seg
.data
);
8935 return E_UNEXPECTED
;
8938 *((INT16
*)data
) = size
;
8940 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8944 str
->offset
= last_offs
;
8951 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8952 WMSFT_TLBFile
*file
)
8957 MSFT_NameIntro
*last_intro
= NULL
;
8959 file
->header
.nametablecount
= 0;
8960 file
->header
.nametablechars
= 0;
8962 file
->name_seg
.len
= 0;
8963 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8966 size
= strlenW(str
->str
);
8967 file
->header
.nametablechars
+= size
;
8968 file
->header
.nametablecount
++;
8970 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8972 return E_UNEXPECTED
;
8974 size
+= sizeof(MSFT_NameIntro
);
8976 size
= (size
+ 4) & ~0x3;
8980 file
->name_seg
.len
+= size
;
8982 /* temporarily use str->offset to store the length of the aligned,
8983 * converted string */
8987 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8988 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
8991 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8993 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8995 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8996 data
+ sizeof(MSFT_NameIntro
),
8997 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8999 heap_free(file
->name_seg
.data
);
9000 return E_UNEXPECTED
;
9002 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9004 intro
->hreftype
= -1; /* TODO? */
9005 intro
->namelen
= size
& 0xFF;
9006 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9007 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9008 intro
->namelen
|= hash
<< 16;
9009 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9010 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9012 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9013 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9015 /* update str->offset to actual value to use in other
9016 * compilation functions that require positions within
9017 * the string table */
9021 str
->offset
= last_offs
;
9026 last_intro
->hreftype
= 0; /* last one is 0? */
9031 static inline int hash_guid(GUID
*guid
)
9035 for (i
= 0; i
< 8; i
++)
9036 hash
^= ((const short *)guid
)[i
];
9041 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9044 MSFT_GuidEntry
*entry
;
9046 int hash_key
, *guidhashtab
;
9048 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9049 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9051 entry
= file
->guid_seg
.data
;
9053 guidhashtab
= file
->guidhash_seg
.data
;
9054 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9055 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9056 entry
->hreftype
= guid
->hreftype
;
9058 hash_key
= hash_guid(&guid
->guid
);
9059 entry
->next_hash
= guidhashtab
[hash_key
];
9060 guidhashtab
[hash_key
] = offs
;
9062 guid
->offset
= offs
;
9063 offs
+= sizeof(MSFT_GuidEntry
);
9070 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9073 VARTYPE arg_type
= V_VT(value
);
9076 DWORD ret
= file
->custdata_seg
.len
;
9078 if(arg_type
== VT_INT
)
9080 if(arg_type
== VT_UINT
)
9084 if(V_VT(value
) != arg_type
) {
9085 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9087 ERR("VariantChangeType failed: %08x\n", hres
);
9092 /* Check if default value can be stored in-place */
9097 if(V_UI4(&v
) > 0x3ffffff)
9110 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9113 /* have to allocate space in custdata_seg */
9122 /* Construct the data to be allocated */
9125 if(file
->custdata_seg
.data
){
9126 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9127 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9128 file
->custdata_seg
.len
+= sizeof(int) * 2;
9130 file
->custdata_seg
.len
= sizeof(int) * 2;
9131 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9134 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9135 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9137 /* TODO: Check if the encoded data is already present in custdata_seg */
9143 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9146 if(file
->custdata_seg
.data
){
9147 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9148 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9149 file
->custdata_seg
.len
+= len
;
9151 file
->custdata_seg
.len
= len
;
9152 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9155 *((unsigned short *)data
) = V_VT(value
);
9156 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9157 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9158 if(V_BSTR(&v
)[i
] <= 0x7f)
9159 data
[i
+6] = V_BSTR(&v
)[i
];
9163 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9164 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9167 /* TODO: Check if the encoded data is already present in custdata_seg */
9172 FIXME("Argument type not yet handled\n");
9177 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9179 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9181 DWORD offs
= file
->arraydesc_seg
.len
;
9185 /* TODO: we should check for duplicates, but that's harder because each
9186 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9187 * at the library-level) */
9189 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9190 if(!file
->arraydesc_seg
.data
)
9191 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9193 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9194 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9196 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9197 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9198 for(i
= 0; i
< desc
->cDims
; ++i
){
9199 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9200 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9206 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9212 VARTYPE vt
, subtype
;
9223 vt
= desc
->vt
& VT_TYPEMASK
;
9225 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9227 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9228 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9230 *out_size
+= 2 * sizeof(DWORD
);
9231 }else if(vt
== VT_CARRAY
){
9232 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9233 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9235 }else if(vt
== VT_USERDEFINED
){
9236 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9237 encoded
[1] = desc
->u
.hreftype
;
9238 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9240 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9258 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9261 data
= file
->typdesc_seg
.data
;
9262 while(offs
< file
->typdesc_seg
.len
){
9263 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9265 offs
+= sizeof(encoded
);
9268 file
->typdesc_seg
.len
+= sizeof(encoded
);
9269 if(!file
->typdesc_seg
.data
)
9270 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9272 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9274 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9279 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9281 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9282 DWORD ret
= cdguids_seg
->len
, offs
;
9283 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
9286 if(list_empty(custdata_list
))
9289 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9290 if(!cdguids_seg
->data
){
9291 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9293 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9295 offs
= ret
+ sizeof(MSFT_CDGuid
);
9296 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9297 cdguid
->GuidOffset
= cd
->guid
->offset
;
9298 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9299 cdguid
->next
= offs
;
9300 offs
+= sizeof(MSFT_CDGuid
);
9310 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9311 WMSFT_TLBFile
*file
)
9313 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9314 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9315 MSFT_VarRecord
*varrecord
;
9316 MSFT_FuncRecord
*funcrecord
;
9318 DWORD
*name
, *offsets
, offs
;
9320 for(i
= 0; i
< info
->cFuncs
; ++i
){
9321 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9323 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9325 /* optional fields */
9326 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9327 if(!list_empty(&desc
->custdata_list
))
9328 recorded_size
+= 7 * sizeof(INT
);
9329 else if(desc
->HelpStringContext
!= 0)
9330 recorded_size
+= 6 * sizeof(INT
);
9332 else if(desc
->Entry
)
9333 recorded_size
+= 3 * sizeof(INT
);
9334 else if(desc
->HelpString
)
9335 recorded_size
+= 2 * sizeof(INT
);
9336 else if(desc
->helpcontext
)
9337 recorded_size
+= sizeof(INT
);
9339 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9341 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9342 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9343 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9348 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9351 for(i
= 0; i
< info
->cVars
; ++i
){
9352 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9354 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9356 /* optional fields */
9357 if(desc
->HelpStringContext
!= 0)
9358 recorded_size
+= 5 * sizeof(INT
);
9359 else if(!list_empty(&desc
->custdata_list
))
9360 recorded_size
+= 4 * sizeof(INT
);
9362 else if(desc
->HelpString
)
9363 recorded_size
+= 2 * sizeof(INT
);
9364 else if(desc
->HelpContext
!= 0)
9365 recorded_size
+= sizeof(INT
);
9367 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9370 if(!recorded_size
&& !extra_size
)
9373 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9375 aux_seg
->len
+= recorded_size
+ extra_size
;
9377 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9380 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9382 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9384 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9386 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9389 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9390 for(i
= 0; i
< info
->cFuncs
; ++i
){
9391 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9392 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9394 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9395 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9396 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9397 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9400 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9405 * ^has_param_defaults
9406 * ^oEntry_is_intresource
9408 funcrecord
->FKCCIC
=
9409 desc
->funcdesc
.funckind
|
9410 (desc
->funcdesc
.invkind
<< 3) |
9411 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9412 (desc
->funcdesc
.callconv
<< 8);
9414 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9415 funcrecord
->FKCCIC
|= 0x2000;
9417 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9418 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9419 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9420 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9423 if(paramdefault_size
> 0)
9424 funcrecord
->FKCCIC
|= 0x1000;
9426 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9427 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9429 /* optional fields */
9431 if(!list_empty(&desc
->custdata_list
)){
9432 size
+= 7 * sizeof(INT
);
9433 funcrecord
->HelpContext
= desc
->helpcontext
;
9434 if(desc
->HelpString
)
9435 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9437 funcrecord
->oHelpString
= -1;
9439 funcrecord
->oEntry
= -1;
9440 else if(IS_INTRESOURCE(desc
->Entry
))
9441 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9443 funcrecord
->oEntry
= desc
->Entry
->offset
;
9444 funcrecord
->res9
= -1;
9445 funcrecord
->resA
= -1;
9446 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9447 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9448 }else if(desc
->HelpStringContext
!= 0){
9449 size
+= 6 * sizeof(INT
);
9450 funcrecord
->HelpContext
= desc
->helpcontext
;
9451 if(desc
->HelpString
)
9452 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9454 funcrecord
->oHelpString
= -1;
9456 funcrecord
->oEntry
= -1;
9457 else if(IS_INTRESOURCE(desc
->Entry
))
9458 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9460 funcrecord
->oEntry
= desc
->Entry
->offset
;
9461 funcrecord
->res9
= -1;
9462 funcrecord
->resA
= -1;
9463 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9464 }else if(desc
->Entry
){
9465 size
+= 3 * sizeof(INT
);
9466 funcrecord
->HelpContext
= desc
->helpcontext
;
9467 if(desc
->HelpString
)
9468 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9470 funcrecord
->oHelpString
= -1;
9472 funcrecord
->oEntry
= -1;
9473 else if(IS_INTRESOURCE(desc
->Entry
))
9474 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9476 funcrecord
->oEntry
= desc
->Entry
->offset
;
9477 }else if(desc
->HelpString
){
9478 size
+= 2 * sizeof(INT
);
9479 funcrecord
->HelpContext
= desc
->helpcontext
;
9480 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9481 }else if(desc
->helpcontext
){
9482 size
+= sizeof(INT
);
9483 funcrecord
->HelpContext
= desc
->helpcontext
;
9486 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9487 size
+= paramdefault_size
;
9489 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9490 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9492 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9493 if(desc
->pParamDesc
[j
].Name
)
9494 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9497 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9499 if(paramdefault_size
){
9500 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9501 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9502 else if(paramdefault_size
)
9507 size
+= sizeof(MSFT_ParameterInfo
);
9510 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9516 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9519 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9520 for(i
= 0; i
< info
->cVars
; ++i
){
9521 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9522 DWORD size
= 5 * sizeof(INT
);
9524 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9525 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9526 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9527 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9529 if(desc
->vardesc
.varkind
== VAR_CONST
){
9530 varrecord
->vardescsize
+= sizeof(VARIANT
);
9531 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9533 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9536 if(desc
->HelpStringContext
!= 0){
9537 size
+= 5 * sizeof(INT
);
9538 varrecord
->HelpContext
= desc
->HelpContext
;
9539 if(desc
->HelpString
)
9540 varrecord
->HelpString
= desc
->HelpString
->offset
;
9542 varrecord
->HelpString
= -1;
9543 varrecord
->res9
= -1;
9544 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9545 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9546 }else if(!list_empty(&desc
->custdata_list
)){
9547 size
+= 4 * sizeof(INT
);
9548 varrecord
->HelpContext
= desc
->HelpContext
;
9549 if(desc
->HelpString
)
9550 varrecord
->HelpString
= desc
->HelpString
->offset
;
9552 varrecord
->HelpString
= -1;
9553 varrecord
->res9
= -1;
9554 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9555 }else if(desc
->HelpString
){
9556 size
+= 2 * sizeof(INT
);
9557 varrecord
->HelpContext
= desc
->HelpContext
;
9558 if(desc
->HelpString
)
9559 varrecord
->HelpString
= desc
->HelpString
->offset
;
9561 varrecord
->HelpString
= -1;
9562 }else if(desc
->HelpContext
!= 0){
9563 size
+= sizeof(INT
);
9564 varrecord
->HelpContext
= desc
->HelpContext
;
9567 varrecord
->Info
= size
| (i
<< 16);
9573 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9576 memid
= (MEMBERID
*)varrecord
;
9577 for(i
= 0; i
< info
->cFuncs
; ++i
){
9578 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9579 *memid
= desc
->funcdesc
.memid
;
9582 for(i
= 0; i
< info
->cVars
; ++i
){
9583 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9584 *memid
= desc
->vardesc
.memid
;
9588 name
= (UINT
*)memid
;
9589 for(i
= 0; i
< info
->cFuncs
; ++i
){
9590 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9592 *name
= desc
->Name
->offset
;
9597 for(i
= 0; i
< info
->cVars
; ++i
){
9598 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9600 *name
= desc
->Name
->offset
;
9609 typedef struct tagWMSFT_RefChunk
{
9616 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9618 DWORD offs
= file
->ref_seg
.len
, i
;
9619 WMSFT_RefChunk
*chunk
;
9621 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9622 if(!file
->ref_seg
.data
)
9623 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9625 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9627 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9629 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9630 chunk
->href
= info
->impltypes
[i
].hRef
;
9631 chunk
->res04
= info
->impltypes
[i
].implflags
;
9633 if(i
< info
->cImplTypes
- 1)
9634 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9643 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9647 size
= sizeof(MSFT_TypeInfoBase
);
9650 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9651 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9652 base
->typekind
= TKIND_DISPATCH
;
9654 base
->typekind
= info
->typekind
;
9655 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9656 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9657 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9662 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9668 base
->posguid
= info
->guid
->offset
;
9671 base
->flags
= info
->wTypeFlags
;
9673 base
->NameOffset
= info
->Name
->offset
;
9675 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9676 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9678 base
->NameOffset
= -1;
9680 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9682 base
->docstringoffs
= info
->DocString
->offset
;
9684 base
->docstringoffs
= -1;
9685 base
->helpstringcontext
= info
->dwHelpStringContext
;
9686 base
->helpcontext
= info
->dwHelpContext
;
9687 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9688 base
->cImplTypes
= info
->cImplTypes
;
9689 base
->cbSizeVft
= info
->cbSizeVft
;
9690 base
->size
= info
->cbSizeInstance
;
9691 if(info
->typekind
== TKIND_COCLASS
){
9692 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9693 }else if(info
->typekind
== TKIND_ALIAS
){
9694 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9695 }else if(info
->typekind
== TKIND_MODULE
){
9697 base
->datatype1
= info
->DllName
->offset
;
9699 base
->datatype1
= -1;
9701 if(info
->cImplTypes
> 0)
9702 base
->datatype1
= info
->impltypes
[0].hRef
;
9704 base
->datatype1
= -1;
9706 base
->datatype2
= index
; /* FIXME: i think there's more here */
9714 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9718 file
->typeinfo_seg
.len
= 0;
9719 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9720 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9721 *junk
= file
->typeinfo_seg
.len
;
9723 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9726 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9727 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9729 file
->aux_seg
.len
= 0;
9730 file
->aux_seg
.data
= NULL
;
9732 file
->typeinfo_seg
.len
= 0;
9733 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9734 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9735 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9736 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9740 typedef struct tagWMSFT_ImpFile
{
9746 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9749 WMSFT_ImpFile
*impfile
;
9751 DWORD last_offs
= 0;
9753 file
->impfile_seg
.len
= 0;
9754 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9758 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9762 path
= implib
->name
;
9763 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9765 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9768 size
+= sizeof(INT16
);
9770 size
= (size
+ 4) & ~0x3;
9774 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9777 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9779 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9780 int strlen
= 0, size
;
9782 impfile
= (WMSFT_ImpFile
*)data
;
9783 impfile
->guid_offs
= implib
->guid
->offset
;
9784 impfile
->lcid
= implib
->lcid
;
9785 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9787 data
+= sizeof(WMSFT_ImpFile
);
9790 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9794 path
= implib
->name
;
9795 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9796 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9798 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9801 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9803 size
= strlen
+ sizeof(INT16
);
9805 size
= (size
+ 4) & ~0x3;
9808 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9811 implib
->offset
= last_offs
;
9812 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9816 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9819 TLBRefType
*ref_type
;
9822 WMSFT_compile_impfile(This
, file
);
9824 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9825 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9827 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9828 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9829 if(ref_type
->index
== TLB_REF_USE_GUID
){
9830 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9831 info
->oGuid
= ref_type
->guid
->offset
;
9833 info
->oGuid
= ref_type
->index
;
9834 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9840 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9842 file
->guidhash_seg
.len
= 0x80;
9843 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9844 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9847 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9849 file
->namehash_seg
.len
= 0x200;
9850 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9851 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9854 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9856 if(contents
&& contents
->len
){
9857 segdir
->offset
= *running_offset
;
9858 segdir
->length
= contents
->len
;
9859 *running_offset
+= segdir
->length
;
9861 segdir
->offset
= -1;
9865 /* TODO: do these ever change? */
9867 segdir
->res0c
= 0xf;
9870 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9874 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9877 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9881 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9883 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9884 base
->memoffset
+= file_len
;
9891 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9893 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9894 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9895 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9896 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9897 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9898 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9899 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9900 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9901 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9902 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9903 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9904 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9905 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9906 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9909 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9911 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9913 DWORD written
, junk_size
, junk_offs
, running_offset
;
9920 TRACE("%p\n", This
);
9922 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
9923 if(This
->typeinfos
[i
]->needs_layout
)
9924 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
9926 memset(&file
, 0, sizeof(file
));
9928 file
.header
.magic1
= 0x5446534D;
9929 file
.header
.magic2
= 0x00010002;
9930 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9931 file
.header
.lcid2
= This
->set_lcid
;
9932 file
.header
.varflags
= 0x40 | This
->syskind
;
9934 file
.header
.varflags
|= 0x10;
9935 if (This
->HelpStringDll
)
9936 file
.header
.varflags
|= HELPDLLFLAG
;
9937 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
9938 file
.header
.flags
= This
->libflags
;
9939 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9940 file
.header
.helpcontext
= This
->dwHelpContext
;
9941 file
.header
.res44
= 0x20;
9942 file
.header
.res48
= 0x80;
9943 file
.header
.dispatchpos
= This
->dispatch_href
;
9945 WMSFT_compile_namehash(This
, &file
);
9946 /* do name and string compilation to get offsets for other compilations */
9947 hres
= WMSFT_compile_names(This
, &file
);
9949 WMSFT_free_file(&file
);
9953 hres
= WMSFT_compile_strings(This
, &file
);
9955 WMSFT_free_file(&file
);
9959 WMSFT_compile_guidhash(This
, &file
);
9960 hres
= WMSFT_compile_guids(This
, &file
);
9962 WMSFT_free_file(&file
);
9967 file
.header
.helpfile
= This
->HelpFile
->offset
;
9969 file
.header
.helpfile
= -1;
9972 file
.header
.helpstring
= This
->DocString
->offset
;
9974 file
.header
.helpstring
= -1;
9976 /* do some more segment compilation */
9977 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9978 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9981 file
.header
.NameOffset
= This
->Name
->offset
;
9983 file
.header
.NameOffset
= -1;
9985 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
9988 file
.header
.posguid
= This
->guid
->offset
;
9990 file
.header
.posguid
= -1;
9992 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9993 if(file
.header
.varflags
& HELPDLLFLAG
)
9994 junk_size
+= sizeof(DWORD
);
9996 junk
= heap_alloc_zero(junk_size
);
9997 if(file
.header
.varflags
& HELPDLLFLAG
){
9998 *junk
= This
->HelpStringDll
->offset
;
10007 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10008 WMSFT_compile_impinfo(This
, &file
);
10010 running_offset
= 0;
10012 TRACE("header at: 0x%x\n", running_offset
);
10013 running_offset
+= sizeof(file
.header
);
10015 TRACE("junk at: 0x%x\n", running_offset
);
10016 running_offset
+= junk_size
;
10018 TRACE("segdir at: 0x%x\n", running_offset
);
10019 running_offset
+= sizeof(file
.segdir
);
10021 TRACE("typeinfo at: 0x%x\n", running_offset
);
10022 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10024 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10025 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10027 TRACE("guidtab at: 0x%x\n", running_offset
);
10028 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10030 TRACE("reftab at: 0x%x\n", running_offset
);
10031 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10033 TRACE("impinfo at: 0x%x\n", running_offset
);
10034 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10036 TRACE("impfiles at: 0x%x\n", running_offset
);
10037 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10039 TRACE("namehashtab at: 0x%x\n", running_offset
);
10040 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10042 TRACE("nametab at: 0x%x\n", running_offset
);
10043 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10045 TRACE("stringtab at: 0x%x\n", running_offset
);
10046 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10048 TRACE("typdesc at: 0x%x\n", running_offset
);
10049 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10051 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10052 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10054 TRACE("custdata at: 0x%x\n", running_offset
);
10055 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10057 TRACE("cdguids at: 0x%x\n", running_offset
);
10058 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10060 TRACE("res0e at: 0x%x\n", running_offset
);
10061 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10063 TRACE("res0f at: 0x%x\n", running_offset
);
10064 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10066 TRACE("aux_seg at: 0x%x\n", running_offset
);
10068 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10070 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10071 FILE_ATTRIBUTE_NORMAL
, 0);
10072 if (outfile
== INVALID_HANDLE_VALUE
){
10073 WMSFT_free_file(&file
);
10075 return TYPE_E_IOERROR
;
10078 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10080 WMSFT_free_file(&file
);
10081 CloseHandle(outfile
);
10083 return TYPE_E_IOERROR
;
10086 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10089 WMSFT_free_file(&file
);
10090 CloseHandle(outfile
);
10091 return TYPE_E_IOERROR
;
10094 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10096 WMSFT_free_file(&file
);
10097 CloseHandle(outfile
);
10098 return TYPE_E_IOERROR
;
10101 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10102 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10103 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10104 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10105 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10106 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10107 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10108 WMSFT_write_segment(outfile
, &file
.name_seg
);
10109 WMSFT_write_segment(outfile
, &file
.string_seg
);
10110 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10111 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10112 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10113 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10114 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10116 WMSFT_free_file(&file
);
10118 CloseHandle(outfile
);
10123 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10126 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10127 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10131 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10132 REFGUID guid
, VARIANT
*varVal
)
10134 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10135 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
10139 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10140 ULONG helpStringContext
)
10142 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10143 FIXME("%p %u - stub\n", This
, helpStringContext
);
10147 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10150 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10151 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10154 return E_INVALIDARG
;
10156 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10161 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10162 ICreateTypeLib2_fnQueryInterface
,
10163 ICreateTypeLib2_fnAddRef
,
10164 ICreateTypeLib2_fnRelease
,
10165 ICreateTypeLib2_fnCreateTypeInfo
,
10166 ICreateTypeLib2_fnSetName
,
10167 ICreateTypeLib2_fnSetVersion
,
10168 ICreateTypeLib2_fnSetGuid
,
10169 ICreateTypeLib2_fnSetDocString
,
10170 ICreateTypeLib2_fnSetHelpFileName
,
10171 ICreateTypeLib2_fnSetHelpContext
,
10172 ICreateTypeLib2_fnSetLcid
,
10173 ICreateTypeLib2_fnSetLibFlags
,
10174 ICreateTypeLib2_fnSaveAllChanges
,
10175 ICreateTypeLib2_fnDeleteTypeInfo
,
10176 ICreateTypeLib2_fnSetCustData
,
10177 ICreateTypeLib2_fnSetHelpStringContext
,
10178 ICreateTypeLib2_fnSetHelpStringDll
10181 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10182 REFIID riid
, void **object
)
10184 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10186 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10189 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10191 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10193 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10196 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10198 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10200 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10203 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10206 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10208 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10210 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10215 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10218 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10222 TRACE("%p %x\n", This
, typeFlags
);
10224 if (typeFlags
& TYPEFLAG_FDUAL
) {
10225 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10227 ITypeInfo
*dispatch
;
10231 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10235 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10236 ITypeLib_Release(stdole
);
10240 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10241 ITypeInfo_Release(dispatch
);
10246 old_flags
= This
->wTypeFlags
;
10247 This
->wTypeFlags
= typeFlags
;
10249 hres
= ICreateTypeInfo2_LayOut(iface
);
10250 if (FAILED(hres
)) {
10251 This
->wTypeFlags
= old_flags
;
10258 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10261 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10263 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10266 return E_INVALIDARG
;
10268 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10273 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10276 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10278 TRACE("%p %d\n", This
, helpContext
);
10280 This
->dwHelpContext
= helpContext
;
10285 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10286 WORD majorVerNum
, WORD minorVerNum
)
10288 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10290 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10292 This
->wMajorVerNum
= majorVerNum
;
10293 This
->wMinorVerNum
= minorVerNum
;
10298 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10299 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10301 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10303 ITypeLib
*container
;
10304 TLBRefType
*ref_type
;
10306 TYPEATTR
*typeattr
;
10310 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10312 if (!typeInfo
|| !refType
)
10313 return E_INVALIDARG
;
10315 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10319 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10320 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10322 ITypeLib_Release(container
);
10324 *refType
= target
->hreftype
;
10329 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10330 if (FAILED(hres
)) {
10331 ITypeLib_Release(container
);
10335 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10336 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10337 implib
->lcid
== libattr
->lcid
&&
10338 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10339 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10343 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10344 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10346 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10347 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10348 implib
->name
= SysAllocString(our_container
->path
);
10350 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10351 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10353 implib
->name
= NULL
;
10354 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10358 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10359 implib
->lcid
= libattr
->lcid
;
10360 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10361 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10363 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10366 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10367 ITypeLib_Release(container
);
10369 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10374 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10375 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10376 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10377 ref_type
->tkind
== typeattr
->typekind
)
10382 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10383 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10385 ref_type
->tkind
= typeattr
->typekind
;
10386 ref_type
->pImpTLInfo
= implib
;
10387 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10389 ref_type
->index
= TLB_REF_USE_GUID
;
10391 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10393 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10396 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10398 *refType
= ref_type
->reference
| 0x1;
10400 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10401 This
->pTypeLib
->dispatch_href
= *refType
;
10406 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10407 UINT index
, FUNCDESC
*funcDesc
)
10409 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10410 TLBFuncDesc tmp_func_desc
, *func_desc
;
10415 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10417 if (!funcDesc
|| funcDesc
->oVft
& 3)
10418 return E_INVALIDARG
;
10420 switch (This
->typekind
) {
10422 if (funcDesc
->funckind
!= FUNC_STATIC
)
10423 return TYPE_E_BADMODULEKIND
;
10425 case TKIND_DISPATCH
:
10426 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10427 return TYPE_E_BADMODULEKIND
;
10430 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10431 return TYPE_E_BADMODULEKIND
;
10434 if (index
> This
->cFuncs
)
10435 return TYPE_E_ELEMENTNOTFOUND
;
10437 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10438 !funcDesc
->cParams
)
10439 return TYPE_E_INCONSISTENTPROPFUNCS
;
10442 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10443 funcDesc
->oVft
% 8 != 0)
10444 return E_INVALIDARG
;
10447 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10448 TLBFuncDesc_Constructor(&tmp_func_desc
);
10450 tmp_func_desc
.funcdesc
= *funcDesc
;
10452 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10453 tmp_func_desc
.funcdesc
.oVft
|= 1;
10455 if (funcDesc
->cScodes
) {
10456 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10457 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10459 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10461 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10462 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10463 buf_size
+= sizeof(ELEMDESC
);
10464 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10466 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10467 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10469 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10470 if (FAILED(hres
)) {
10471 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10472 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10476 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10477 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10478 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10479 if (FAILED(hres
)) {
10480 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10481 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10484 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10485 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10486 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10487 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10488 if (FAILED(hres
)) {
10489 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10490 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10496 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10498 if (This
->funcdescs
) {
10499 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10500 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10502 if (index
< This
->cFuncs
) {
10503 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10504 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10505 func_desc
= This
->funcdescs
+ index
;
10507 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10509 /* move custdata lists to the new memory location */
10510 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10512 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10513 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10514 list_init(&fd
->custdata_list
);
10516 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10517 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10522 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10524 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10525 list_init(&func_desc
->custdata_list
);
10529 This
->needs_layout
= TRUE
;
10534 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10535 UINT index
, HREFTYPE refType
)
10537 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10538 TLBImplType
*impl_type
;
10541 TRACE("%p %u %d\n", This
, index
, refType
);
10543 switch(This
->typekind
){
10544 case TKIND_COCLASS
: {
10546 FIXME("Unhandled index: -1\n");
10550 if(index
!= This
->cImplTypes
)
10551 return TYPE_E_ELEMENTNOTFOUND
;
10555 case TKIND_INTERFACE
:
10556 case TKIND_DISPATCH
:
10557 if (index
!= 0 || This
->cImplTypes
)
10558 return TYPE_E_ELEMENTNOTFOUND
;
10561 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10565 if (This
->impltypes
){
10568 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10569 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10571 if (index
< This
->cImplTypes
) {
10572 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10573 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10574 impl_type
= This
->impltypes
+ index
;
10576 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10578 /* move custdata lists to the new memory location */
10579 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10581 TLBImplType
*it
= &This
->impltypes
[i
];
10582 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10583 list_init(&it
->custdata_list
);
10585 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10586 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10591 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10593 memset(impl_type
, 0, sizeof(TLBImplType
));
10594 TLBImplType_Constructor(impl_type
);
10595 impl_type
->hRef
= refType
;
10597 ++This
->cImplTypes
;
10599 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10600 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10602 hres
= ICreateTypeInfo2_LayOut(iface
);
10609 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10610 UINT index
, INT implTypeFlags
)
10612 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10613 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10615 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10617 if (This
->typekind
!= TKIND_COCLASS
)
10618 return TYPE_E_BADMODULEKIND
;
10620 if (index
>= This
->cImplTypes
)
10621 return TYPE_E_ELEMENTNOTFOUND
;
10623 impl_type
->implflags
= implTypeFlags
;
10628 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10631 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10633 TRACE("%p %d\n", This
, alignment
);
10635 This
->cbAlignment
= alignment
;
10640 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10643 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10645 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10648 return E_INVALIDARG
;
10650 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10652 This
->lpstrSchema
= This
->Schema
->str
;
10657 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10658 UINT index
, VARDESC
*varDesc
)
10660 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10661 TLBVarDesc
*var_desc
;
10663 TRACE("%p %u %p\n", This
, index
, varDesc
);
10665 if (This
->vardescs
){
10668 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10669 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10671 if (index
< This
->cVars
) {
10672 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10673 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10674 var_desc
= This
->vardescs
+ index
;
10676 var_desc
= This
->vardescs
+ This
->cVars
;
10678 /* move custdata lists to the new memory location */
10679 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10681 TLBVarDesc
*var
= &This
->vardescs
[i
];
10682 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10683 list_init(&var
->custdata_list
);
10685 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10686 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10691 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10693 TLBVarDesc_Constructor(var_desc
);
10694 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10695 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10699 This
->needs_layout
= TRUE
;
10704 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10705 UINT index
, LPOLESTR
*names
, UINT numNames
)
10707 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10708 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10711 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10714 return E_INVALIDARG
;
10716 if (index
>= This
->cFuncs
|| numNames
== 0)
10717 return TYPE_E_ELEMENTNOTFOUND
;
10719 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10720 if(numNames
> func_desc
->funcdesc
.cParams
)
10721 return TYPE_E_ELEMENTNOTFOUND
;
10723 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10724 return TYPE_E_ELEMENTNOTFOUND
;
10726 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10727 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10728 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10729 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10730 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10731 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10733 return TYPE_E_AMBIGUOUSNAME
;
10737 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10739 for (i
= 1; i
< numNames
; ++i
) {
10740 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10741 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10747 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10748 UINT index
, LPOLESTR name
)
10750 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10752 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10755 return E_INVALIDARG
;
10757 if(index
>= This
->cVars
)
10758 return TYPE_E_ELEMENTNOTFOUND
;
10760 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10764 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10765 TYPEDESC
*tdescAlias
)
10767 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10770 TRACE("%p %p\n", This
, tdescAlias
);
10773 return E_INVALIDARG
;
10775 if(This
->typekind
!= TKIND_ALIAS
)
10776 return TYPE_E_BADMODULEKIND
;
10778 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->cbSizeInstance
, &This
->cbAlignment
);
10782 heap_free(This
->tdescAlias
);
10783 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10784 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10789 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10790 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10792 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10793 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10797 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10798 UINT index
, LPOLESTR docString
)
10800 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10801 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10803 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10806 return E_INVALIDARG
;
10808 if(index
>= This
->cFuncs
)
10809 return TYPE_E_ELEMENTNOTFOUND
;
10811 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10816 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10817 UINT index
, LPOLESTR docString
)
10819 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10820 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10822 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10825 return E_INVALIDARG
;
10827 if(index
>= This
->cVars
)
10828 return TYPE_E_ELEMENTNOTFOUND
;
10830 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10835 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10836 UINT index
, DWORD helpContext
)
10838 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10839 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10841 TRACE("%p %u %d\n", This
, index
, helpContext
);
10843 if(index
>= This
->cFuncs
)
10844 return TYPE_E_ELEMENTNOTFOUND
;
10846 func_desc
->helpcontext
= helpContext
;
10851 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10852 UINT index
, DWORD helpContext
)
10854 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10855 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10857 TRACE("%p %u %d\n", This
, index
, helpContext
);
10859 if(index
>= This
->cVars
)
10860 return TYPE_E_ELEMENTNOTFOUND
;
10862 var_desc
->HelpContext
= helpContext
;
10867 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10868 UINT index
, BSTR bstrMops
)
10870 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10871 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10875 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10878 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10880 TRACE("%p %p\n", This
, idlDesc
);
10883 return E_INVALIDARG
;
10885 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10886 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10891 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10893 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10895 TLBFuncDesc
*func_desc
;
10896 UINT user_vft
= 0, i
, depth
= 0;
10897 HRESULT hres
= S_OK
;
10899 TRACE("%p\n", This
);
10901 This
->needs_layout
= FALSE
;
10903 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10907 if (This
->typekind
== TKIND_INTERFACE
) {
10912 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10914 if (SUCCEEDED(hres
)) {
10915 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10917 if (SUCCEEDED(hres
)) {
10918 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10919 if (FAILED(hres
)) {
10920 ITypeInfo_Release(inh
);
10921 ITypeInfo_Release(tinfo
);
10924 This
->cbSizeVft
= attr
->cbSizeVft
;
10925 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10929 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10930 if(SUCCEEDED(hres
)){
10932 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10933 if(SUCCEEDED(hres
)){
10934 ITypeInfo_Release(inh
);
10938 }while(SUCCEEDED(hres
));
10941 ITypeInfo_Release(inh
);
10942 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10943 This
->cbSizeVft
= 0;
10946 ITypeInfo_Release(tinfo
);
10949 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10950 This
->cbSizeVft
= 0;
10953 ITypeInfo_Release(tinfo
);
10956 } else if (This
->typekind
== TKIND_DISPATCH
)
10957 This
->cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10959 This
->cbSizeVft
= 0;
10961 func_desc
= This
->funcdescs
;
10963 while (i
< This
->cFuncs
) {
10964 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10965 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
10967 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10968 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10970 This
->cbSizeVft
+= This
->pTypeLib
->ptr_size
;
10972 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10975 BOOL reset
= FALSE
;
10977 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10979 iter
= This
->funcdescs
;
10980 while (j
< This
->cFuncs
) {
10981 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10983 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
10986 ++func_desc
->funcdesc
.memid
;
10987 iter
= This
->funcdescs
;
11000 if (user_vft
> This
->cbSizeVft
)
11001 This
->cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11003 for(i
= 0; i
< This
->cVars
; ++i
){
11004 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11005 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11007 BOOL reset
= FALSE
;
11010 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11012 iter
= This
->vardescs
;
11013 while (j
< This
->cVars
) {
11014 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11016 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->cVars
;
11019 ++var_desc
->vardesc
.memid
;
11020 iter
= This
->vardescs
;
11030 ITypeInfo_Release(tinfo
);
11034 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11037 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11038 FIXME("%p %u - stub\n", This
, index
);
11042 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11043 MEMBERID memid
, INVOKEKIND invKind
)
11045 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11046 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11050 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11053 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11054 FIXME("%p %u - stub\n", This
, index
);
11058 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11061 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11062 FIXME("%p %x - stub\n", This
, memid
);
11066 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11069 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11070 FIXME("%p %u - stub\n", This
, index
);
11074 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11075 REFGUID guid
, VARIANT
*varVal
)
11079 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11081 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11083 if (!guid
|| !varVal
)
11084 return E_INVALIDARG
;
11086 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11088 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11091 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11092 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11094 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11095 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11099 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11100 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11102 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11103 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11107 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11108 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11110 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11111 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11115 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11116 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11118 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11119 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11123 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11124 ULONG helpStringContext
)
11126 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11128 TRACE("%p %u\n", This
, helpStringContext
);
11130 This
->dwHelpStringContext
= helpStringContext
;
11135 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11136 UINT index
, ULONG helpStringContext
)
11138 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11139 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11143 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11144 UINT index
, ULONG helpStringContext
)
11146 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11147 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11151 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11153 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11154 FIXME("%p - stub\n", This
);
11158 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11161 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11163 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11166 return E_INVALIDARG
;
11168 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11173 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11174 ICreateTypeInfo2_fnQueryInterface
,
11175 ICreateTypeInfo2_fnAddRef
,
11176 ICreateTypeInfo2_fnRelease
,
11177 ICreateTypeInfo2_fnSetGuid
,
11178 ICreateTypeInfo2_fnSetTypeFlags
,
11179 ICreateTypeInfo2_fnSetDocString
,
11180 ICreateTypeInfo2_fnSetHelpContext
,
11181 ICreateTypeInfo2_fnSetVersion
,
11182 ICreateTypeInfo2_fnAddRefTypeInfo
,
11183 ICreateTypeInfo2_fnAddFuncDesc
,
11184 ICreateTypeInfo2_fnAddImplType
,
11185 ICreateTypeInfo2_fnSetImplTypeFlags
,
11186 ICreateTypeInfo2_fnSetAlignment
,
11187 ICreateTypeInfo2_fnSetSchema
,
11188 ICreateTypeInfo2_fnAddVarDesc
,
11189 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11190 ICreateTypeInfo2_fnSetVarName
,
11191 ICreateTypeInfo2_fnSetTypeDescAlias
,
11192 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11193 ICreateTypeInfo2_fnSetFuncDocString
,
11194 ICreateTypeInfo2_fnSetVarDocString
,
11195 ICreateTypeInfo2_fnSetFuncHelpContext
,
11196 ICreateTypeInfo2_fnSetVarHelpContext
,
11197 ICreateTypeInfo2_fnSetMops
,
11198 ICreateTypeInfo2_fnSetTypeIdldesc
,
11199 ICreateTypeInfo2_fnLayOut
,
11200 ICreateTypeInfo2_fnDeleteFuncDesc
,
11201 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11202 ICreateTypeInfo2_fnDeleteVarDesc
,
11203 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11204 ICreateTypeInfo2_fnDeleteImplType
,
11205 ICreateTypeInfo2_fnSetCustData
,
11206 ICreateTypeInfo2_fnSetFuncCustData
,
11207 ICreateTypeInfo2_fnSetParamCustData
,
11208 ICreateTypeInfo2_fnSetVarCustData
,
11209 ICreateTypeInfo2_fnSetImplTypeCustData
,
11210 ICreateTypeInfo2_fnSetHelpStringContext
,
11211 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11212 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11213 ICreateTypeInfo2_fnInvalidate
,
11214 ICreateTypeInfo2_fnSetName
11217 /******************************************************************************
11218 * ClearCustData (OLEAUT32.171)
11220 * Clear a custom data type's data.
11223 * lpCust [I] The custom data type instance
11228 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11230 if (lpCust
&& lpCust
->cCustData
)
11232 if (lpCust
->prgCustData
)
11236 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11237 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11239 CoTaskMemFree(lpCust
->prgCustData
);
11240 lpCust
->prgCustData
= NULL
;
11242 lpCust
->cCustData
= 0;