4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
46 * -. lousy fatal error handling
51 #include "wine/port.h"
60 #define NONAMELESSUNION
71 #include "wine/unicode.h"
74 #include "wine/debug.h"
76 #include "wine/list.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
79 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
93 WORD type_id
; /* Type identifier */
94 WORD count
; /* Number of resources of this type */
95 DWORD resloader
; /* SetResourceHandler() */
101 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
102 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
103 static void TLB_FreeVarDesc(VARDESC
*);
105 /****************************************************************************
108 * Takes p_iVal (which is in little endian) and returns it
109 * in the host machine's byte order.
111 #ifdef WORDS_BIGENDIAN
112 static WORD
FromLEWord(WORD p_iVal
)
114 return (((p_iVal
& 0x00FF) << 8) |
115 ((p_iVal
& 0xFF00) >> 8));
119 static DWORD
FromLEDWord(DWORD p_iVal
)
121 return (((p_iVal
& 0x000000FF) << 24) |
122 ((p_iVal
& 0x0000FF00) << 8) |
123 ((p_iVal
& 0x00FF0000) >> 8) |
124 ((p_iVal
& 0xFF000000) >> 24));
127 #define FromLEWord(X) (X)
128 #define FromLEDWord(X) (X)
131 #define DISPATCH_HREF_OFFSET 0x01000000
132 #define DISPATCH_HREF_MASK 0xff000000
134 /****************************************************************************
137 * Fix byte order in any structure if necessary
139 #ifdef WORDS_BIGENDIAN
140 static void FromLEWords(void *p_Val
, int p_iSize
)
144 p_iSize
/= sizeof(WORD
);
147 *Val
= FromLEWord(*Val
);
154 static void FromLEDWords(void *p_Val
, int p_iSize
)
158 p_iSize
/= sizeof(DWORD
);
161 *Val
= FromLEDWord(*Val
);
167 #define FromLEWords(X,Y) /*nothing*/
168 #define FromLEDWords(X,Y) /*nothing*/
172 * Find a typelib key which matches a requested maj.min version.
174 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
176 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
180 INT best_maj
= -1, best_min
= -1;
183 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
184 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
186 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
189 len
= sizeof(key_name
);
191 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
195 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
197 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
199 if (*wMaj
== 0xffff && *wMin
== 0xffff)
201 if (v_maj
> best_maj
) best_maj
= v_maj
;
202 if (v_min
> best_min
) best_min
= v_min
;
204 else if (*wMaj
== v_maj
)
211 break; /* exact match */
213 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
216 len
= sizeof(key_name
);
220 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
222 if (*wMaj
== 0xffff && *wMin
== 0xffff)
224 if (best_maj
>= 0 && best_min
>= 0)
232 if (*wMaj
== best_maj
&& best_min
>= 0)
240 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
241 /* buffer must be at least 60 characters long */
242 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
244 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
245 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
247 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
248 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
249 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
253 /* get the path of an interface key, in the form "Interface\\<guid>" */
254 /* buffer must be at least 50 characters long */
255 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
257 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
259 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
260 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
264 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
265 /* buffer must be at least 16 characters long */
266 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
268 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
269 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
270 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
271 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
273 sprintfW( buffer
, LcidFormatW
, lcid
);
276 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
277 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
278 case SYS_WIN64
: strcatW( buffer
, win64W
); break;
280 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
286 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
288 struct tlibredirect_data
302 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
303 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
304 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
306 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
310 WCHAR Path
[MAX_PATH
];
313 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
317 ACTCTX_SECTION_KEYED_DATA data
;
319 data
.cbSize
= sizeof(data
);
320 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
322 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
326 if ((wMaj
!= 0xffff || wMin
!= 0xffff) && (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
))
327 return TYPE_E_LIBNOTREGISTERED
;
329 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
330 len
= SearchPathW( NULL
, nameW
, NULL
, sizeof(Path
)/sizeof(WCHAR
), Path
, NULL
);
331 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
333 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
334 *path
= SysAllocString( Path
);
339 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
340 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
342 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
343 if (res
== ERROR_FILE_NOT_FOUND
)
345 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
346 return TYPE_E_LIBNOTREGISTERED
;
348 else if (res
!= ERROR_SUCCESS
)
350 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
351 return TYPE_E_REGISTRYACCESS
;
356 LONG dwPathLen
= sizeof(Path
);
358 get_lcid_subkey( myLCID
, syskind
, buffer
);
360 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
364 else if (myLCID
== lcid
)
366 /* try with sub-langid */
367 myLCID
= SUBLANGID(lcid
);
369 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
371 /* try with system langid */
381 *path
= SysAllocString( Path
);
386 TRACE_(typelib
)("-- 0x%08x\n", hr
);
390 /****************************************************************************
391 * QueryPathOfRegTypeLib [OLEAUT32.164]
393 * Gets the path to a registered type library.
396 * guid [I] referenced guid
397 * wMaj [I] major version
398 * wMin [I] minor version
400 * path [O] path of typelib
404 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
405 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
408 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
412 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
417 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
420 /******************************************************************************
421 * CreateTypeLib [OLEAUT32.160] creates a typelib
427 HRESULT WINAPI
CreateTypeLib(
428 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
430 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
434 /******************************************************************************
435 * LoadTypeLib [OLEAUT32.161]
437 * Loads a type library
440 * szFile [I] Name of file to load from.
441 * pptLib [O] Pointer that receives ITypeLib object on success.
448 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
450 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
452 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
453 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
456 /******************************************************************************
457 * LoadTypeLibEx [OLEAUT32.183]
459 * Loads and optionally registers a type library
465 HRESULT WINAPI
LoadTypeLibEx(
466 LPCOLESTR szFile
, /* [in] Name of file to load from */
467 REGKIND regkind
, /* [in] Specify kind of registration */
468 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
470 WCHAR szPath
[MAX_PATH
+1];
473 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
475 if (!szFile
|| !pptLib
)
480 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
485 case REGKIND_DEFAULT
:
486 /* don't register typelibs supplied with full path. Experimentation confirms the following */
487 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
488 (szFile
[0] && (szFile
[1] == ':'))) break;
489 /* else fall-through */
491 case REGKIND_REGISTER
:
492 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
494 ITypeLib_Release(*pptLib
);
502 TRACE(" returns %08x\n",res
);
506 /******************************************************************************
507 * LoadRegTypeLib [OLEAUT32.162]
509 * Loads a registered type library.
512 * rguid [I] GUID of the registered type library.
513 * wVerMajor [I] major version.
514 * wVerMinor [I] minor version.
515 * lcid [I] locale ID.
516 * ppTLib [O] pointer that receives an ITypeLib object on success.
520 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
523 HRESULT WINAPI
LoadRegTypeLib(
535 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
539 res
= LoadTypeLib(bstr
, ppTLib
);
542 if ((wVerMajor
!=0xffff || wVerMinor
!=0xffff) && *ppTLib
)
546 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
549 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
550 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
554 ITypeLib_Release(*ppTLib
);
556 res
= TYPE_E_LIBNOTREGISTERED
;
562 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
568 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
569 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
570 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
571 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
572 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
573 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
575 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
580 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
581 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
582 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
584 get_interface_key( &tattr
->guid
, keyName
);
585 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
586 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
589 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
590 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
592 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
593 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
594 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
595 (const BYTE
*)PSOA
, sizeof PSOA
);
599 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
600 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
601 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
602 (const BYTE
*)PSOA
, sizeof PSOA
);
606 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
607 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
610 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
611 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
613 StringFromGUID2(&libattr
->guid
, buffer
, 40);
614 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
615 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
616 sprintfW(buffer
, fmtver
, libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
617 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
618 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
626 /******************************************************************************
627 * RegisterTypeLib [OLEAUT32.163]
628 * Adds information about a type library to the System Registry
630 * Docs: ITypeLib FAR * ptlib
631 * Docs: OLECHAR FAR* szFullPath
632 * Docs: OLECHAR FAR* szHelpDir
638 HRESULT WINAPI
RegisterTypeLib(
639 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
640 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
641 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
653 if (ptlib
== NULL
|| szFullPath
== NULL
)
656 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
660 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
663 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
666 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
667 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
671 /* Set the human-readable name of the typelib */
672 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
676 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
677 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
683 /* Make up the name of the typelib path subkey */
684 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
686 /* Create the typelib path subkey */
687 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
688 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
690 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
691 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
699 /* Create the flags subkey */
700 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
701 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
703 /* FIXME: is %u correct? */
704 static const WCHAR formatW
[] = {'%','u',0};
706 sprintfW(buf
, formatW
, attr
->wLibFlags
);
707 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
708 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
716 /* create the helpdir subkey */
717 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
718 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
720 BOOL freeHelpDir
= FALSE
;
723 /* if we created a new key, and helpDir was null, set the helpdir
724 to the directory which contains the typelib. However,
725 if we just opened an existing key, we leave the helpdir alone */
726 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
727 szHelpDir
= SysAllocString(szFullPath
);
728 pIndexStr
= strrchrW(szHelpDir
, '\\');
735 /* if we have an szHelpDir, set it! */
736 if (szHelpDir
!= NULL
) {
737 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
738 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
744 if (freeHelpDir
) SysFreeString(szHelpDir
);
756 /* register OLE Automation-compatible interfaces for this typelib */
757 types
= ITypeLib_GetTypeInfoCount(ptlib
);
758 for (tidx
=0; tidx
<types
; tidx
++) {
759 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
760 LPOLESTR name
= NULL
;
761 ITypeInfo
*tinfo
= NULL
;
763 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
766 case TKIND_INTERFACE
:
767 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
768 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
772 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
773 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
777 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
782 TYPEATTR
*tattr
= NULL
;
783 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
786 TRACE_(typelib
)("guid=%s, flags=%04x (",
787 debugstr_guid(&tattr
->guid
),
790 if (TRACE_ON(typelib
)) {
791 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
811 /* Register all dispinterfaces (which includes dual interfaces) and
812 oleautomation interfaces */
813 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
814 kind
== TKIND_DISPATCH
)
817 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
819 /* register interface<->typelib coupling */
820 TLB_register_interface(attr
, name
, tattr
, 0);
822 /* register TLBs into the opposite registry view, too */
823 if(opposite
== KEY_WOW64_32KEY
||
824 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
825 TLB_register_interface(attr
, name
, tattr
, opposite
);
828 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
831 ITypeInfo_Release(tinfo
);
838 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
843 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
845 WCHAR subKeyName
[50];
848 /* the path to the type */
849 get_interface_key( guid
, subKeyName
);
851 /* Delete its bits */
852 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
855 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
856 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
857 RegDeleteKeyW(subKey
, TypeLibW
);
859 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
862 /******************************************************************************
863 * UnRegisterTypeLib [OLEAUT32.186]
864 * Removes information about a type library from the System Registry
871 HRESULT WINAPI
UnRegisterTypeLib(
872 REFGUID libid
, /* [in] Guid of the library */
873 WORD wVerMajor
, /* [in] major version */
874 WORD wVerMinor
, /* [in] minor version */
875 LCID lcid
, /* [in] locale id */
878 BSTR tlibPath
= NULL
;
881 WCHAR subKeyName
[50];
884 BOOL deleteOtherStuff
;
886 TYPEATTR
* typeAttr
= NULL
;
888 ITypeInfo
* typeInfo
= NULL
;
889 ITypeLib
* typeLib
= NULL
;
892 TRACE("(IID: %s)\n",debugstr_guid(libid
));
894 /* Create the path to the key */
895 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
897 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
899 TRACE("Unsupported syskind %i\n", syskind
);
900 result
= E_INVALIDARG
;
904 /* get the path to the typelib on disk */
905 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
906 result
= E_INVALIDARG
;
910 /* Try and open the key to the type library. */
911 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
912 result
= E_INVALIDARG
;
916 /* Try and load the type library */
917 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
918 result
= TYPE_E_INVALIDSTATE
;
922 /* remove any types registered with this typelib */
923 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
924 for (i
=0; i
<numTypes
; i
++) {
925 /* get the kind of type */
926 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
930 /* skip non-interfaces, and get type info for the type */
931 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
934 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
937 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
941 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
942 kind
== TKIND_DISPATCH
)
945 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
947 TLB_unregister_interface(&typeAttr
->guid
, 0);
949 /* unregister TLBs into the opposite registry view, too */
950 if(opposite
== KEY_WOW64_32KEY
||
951 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
952 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
957 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
959 if (typeInfo
) ITypeInfo_Release(typeInfo
);
963 /* Now, delete the type library path subkey */
964 get_lcid_subkey( lcid
, syskind
, subKeyName
);
965 RegDeleteKeyW(key
, subKeyName
);
966 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
967 RegDeleteKeyW(key
, subKeyName
);
969 /* check if there is anything besides the FLAGS/HELPDIR keys.
970 If there is, we don't delete them */
971 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
972 deleteOtherStuff
= TRUE
;
974 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
975 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
977 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
978 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
979 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
980 deleteOtherStuff
= FALSE
;
984 /* only delete the other parts of the key if we're absolutely sure */
985 if (deleteOtherStuff
) {
986 RegDeleteKeyW(key
, FLAGSW
);
987 RegDeleteKeyW(key
, HELPDIRW
);
991 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
992 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
993 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
997 SysFreeString(tlibPath
);
998 if (typeLib
) ITypeLib_Release(typeLib
);
999 if (key
) RegCloseKey(key
);
1003 /******************************************************************************
1004 * RegisterTypeLibForUser [OLEAUT32.442]
1005 * Adds information about a type library to the user registry
1007 * Docs: ITypeLib FAR * ptlib
1008 * Docs: OLECHAR FAR* szFullPath
1009 * Docs: OLECHAR FAR* szHelpDir
1015 HRESULT WINAPI
RegisterTypeLibForUser(
1016 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
1017 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
1018 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1021 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1022 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1023 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1026 /******************************************************************************
1027 * UnRegisterTypeLibForUser [OLEAUT32.443]
1028 * Removes information about a type library from the user registry
1034 HRESULT WINAPI
UnRegisterTypeLibForUser(
1035 REFGUID libid
, /* [in] GUID of the library */
1036 WORD wVerMajor
, /* [in] major version */
1037 WORD wVerMinor
, /* [in] minor version */
1038 LCID lcid
, /* [in] locale id */
1041 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1042 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1043 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1046 /*======================= ITypeLib implementation =======================*/
1048 typedef struct tagTLBGuid
{
1055 typedef struct tagTLBCustData
1062 /* data structure for import typelibs */
1063 typedef struct tagTLBImpLib
1065 int offset
; /* offset in the file (MSFT)
1066 offset in nametable (SLTG)
1067 just used to identify library while reading
1069 TLBGuid
*guid
; /* libid */
1070 BSTR name
; /* name */
1072 LCID lcid
; /* lcid of imported typelib */
1074 WORD wVersionMajor
; /* major version number */
1075 WORD wVersionMinor
; /* minor version number */
1077 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1078 NULL if not yet loaded */
1082 typedef struct tagTLBString
{
1088 /* internal ITypeLib data */
1089 typedef struct tagITypeLibImpl
1091 ITypeLib2 ITypeLib2_iface
;
1092 ITypeComp ITypeComp_iface
;
1093 ICreateTypeLib2 ICreateTypeLib2_iface
;
1104 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1105 * exported to the application as a UNICODE string.
1107 struct list string_list
;
1108 struct list name_list
;
1109 struct list guid_list
;
1111 const TLBString
*Name
;
1112 const TLBString
*DocString
;
1113 const TLBString
*HelpFile
;
1114 const TLBString
*HelpStringDll
;
1115 DWORD dwHelpContext
;
1116 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1117 struct tagITypeInfoImpl
**typeinfos
;
1118 struct list custdata_list
;
1119 struct list implib_list
;
1120 int ctTypeDesc
; /* number of items in type desc array */
1121 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1122 library. Only used while reading MSFT
1124 struct list ref_list
; /* list of ref types in this typelib */
1125 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1128 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1134 static const ITypeLib2Vtbl tlbvt
;
1135 static const ITypeCompVtbl tlbtcvt
;
1136 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1138 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1140 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1143 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1145 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1148 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1150 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1153 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1155 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1158 /* ITypeLib methods */
1159 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1160 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1162 /*======================= ITypeInfo implementation =======================*/
1164 /* data for referenced types */
1165 typedef struct tagTLBRefType
1167 INT index
; /* Type index for internal ref or for external ref
1168 it the format is SLTG. -2 indicates to
1172 TLBGuid
*guid
; /* guid of the referenced type */
1173 /* if index == TLB_REF_USE_GUID */
1175 HREFTYPE reference
; /* The href of this ref */
1176 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1177 TLB_REF_INTERNAL for internal refs
1178 TLB_REF_NOT_FOUND for broken refs */
1183 #define TLB_REF_USE_GUID -2
1185 #define TLB_REF_INTERNAL (void*)-2
1186 #define TLB_REF_NOT_FOUND (void*)-1
1188 /* internal Parameter data */
1189 typedef struct tagTLBParDesc
1191 const TLBString
*Name
;
1192 struct list custdata_list
;
1195 /* internal Function data */
1196 typedef struct tagTLBFuncDesc
1198 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1199 const TLBString
*Name
; /* the name of this function */
1200 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1202 int HelpStringContext
;
1203 const TLBString
*HelpString
;
1204 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1205 struct list custdata_list
;
1208 /* internal Variable data */
1209 typedef struct tagTLBVarDesc
1211 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1212 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1213 const TLBString
*Name
; /* the name of this variable */
1215 int HelpStringContext
;
1216 const TLBString
*HelpString
;
1217 struct list custdata_list
;
1220 /* internal implemented interface data */
1221 typedef struct tagTLBImplType
1223 HREFTYPE hRef
; /* hRef of interface */
1224 int implflags
; /* IMPLFLAG_*s */
1225 struct list custdata_list
;
1228 /* internal TypeInfo data */
1229 typedef struct tagITypeInfoImpl
1231 ITypeInfo2 ITypeInfo2_iface
;
1232 ITypeComp ITypeComp_iface
;
1233 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1235 BOOL not_attached_to_typelib
;
1240 TYPEDESC
*tdescAlias
;
1242 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1243 int index
; /* index in this typelib; */
1244 HREFTYPE hreftype
; /* hreftype for app object binding */
1245 /* type libs seem to store the doc strings in ascii
1246 * so why should we do it in unicode?
1248 const TLBString
*Name
;
1249 const TLBString
*DocString
;
1250 const TLBString
*DllName
;
1251 const TLBString
*Schema
;
1252 DWORD dwHelpContext
;
1253 DWORD dwHelpStringContext
;
1256 TLBFuncDesc
*funcdescs
;
1259 TLBVarDesc
*vardescs
;
1261 /* Implemented Interfaces */
1262 TLBImplType
*impltypes
;
1264 struct list
*pcustdata_list
;
1265 struct list custdata_list
;
1268 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1270 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1273 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1275 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1278 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1280 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1283 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1285 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1288 static const ITypeInfo2Vtbl tinfvt
;
1289 static const ITypeCompVtbl tcompvt
;
1290 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1292 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1293 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1295 typedef struct tagTLBContext
1297 unsigned int oStart
; /* start of TLB in file */
1298 unsigned int pos
; /* current pos */
1299 unsigned int length
; /* total length */
1300 void *mapping
; /* memory mapping */
1301 MSFT_SegDir
* pTblDir
;
1302 ITypeLibImpl
* pLibInfo
;
1306 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1308 return str
!= NULL
? str
->str
: NULL
;
1311 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1315 return memcmp(left
, str
->str
, len
);
1318 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1320 return guid
!= NULL
? &guid
->guid
: NULL
;
1323 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1325 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1328 static int get_ptr_size(SYSKIND syskind
)
1338 WARN("Unhandled syskind: 0x%x\n", syskind
);
1345 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1346 if (pTD
->vt
& VT_RESERVED
)
1347 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1348 if (pTD
->vt
& VT_BYREF
)
1349 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1350 if (pTD
->vt
& VT_ARRAY
)
1351 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1352 if (pTD
->vt
& VT_VECTOR
)
1353 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1354 switch(pTD
->vt
& VT_TYPEMASK
) {
1355 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1356 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1357 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1358 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1359 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1360 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1361 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1362 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1363 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1364 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1365 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1366 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1367 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1368 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1369 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1370 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1371 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1372 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1373 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1374 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1375 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1376 pTD
->u
.hreftype
); break;
1377 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1378 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1379 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1380 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1382 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1383 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1385 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1386 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1387 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1390 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1394 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1396 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1397 dump_TypeDesc(&edesc
->tdesc
,buf
);
1398 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1399 MESSAGE("\t\tu.paramdesc.wParamFlags");
1400 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1401 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1402 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1403 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1404 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1405 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1406 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1407 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1408 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1410 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1412 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1413 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1414 MESSAGE("Param %d:\n",i
);
1415 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1417 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1418 switch (funcdesc
->funckind
) {
1419 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1420 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1421 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1422 case FUNC_STATIC
: MESSAGE("static");break;
1423 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1424 default: MESSAGE("unknown");break;
1426 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1427 switch (funcdesc
->invkind
) {
1428 case INVOKE_FUNC
: MESSAGE("func");break;
1429 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1430 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1431 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1433 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1434 switch (funcdesc
->callconv
) {
1435 case CC_CDECL
: MESSAGE("cdecl");break;
1436 case CC_PASCAL
: MESSAGE("pascal");break;
1437 case CC_STDCALL
: MESSAGE("stdcall");break;
1438 case CC_SYSCALL
: MESSAGE("syscall");break;
1441 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1442 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1443 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1445 MESSAGE("\telemdescFunc (return value type):\n");
1446 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1449 static const char * const typekind_desc
[] =
1462 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1465 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1466 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1467 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1470 dump_FUNCDESC(&(pfd
->funcdesc
));
1472 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1473 if(pfd
->Entry
== NULL
)
1474 MESSAGE("\tentry: (null)\n");
1475 else if(pfd
->Entry
== (void*)-1)
1476 MESSAGE("\tentry: invalid\n");
1477 else if(IS_INTRESOURCE(pfd
->Entry
))
1478 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1480 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1482 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1486 dump_TLBFuncDescOne(pfd
);
1491 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1495 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1501 static void dump_TLBImpLib(const TLBImpLib
*import
)
1503 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1504 debugstr_w(import
->name
));
1505 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1506 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1509 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1513 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1515 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1516 if(ref
->index
== -1)
1517 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1519 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1521 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1523 TRACE_(typelib
)("in lib\n");
1524 dump_TLBImpLib(ref
->pImpTLInfo
);
1529 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1534 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1535 impl
->hRef
, impl
->implflags
);
1541 static void dump_DispParms(const DISPPARAMS
* pdp
)
1545 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1547 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1549 TRACE("named args:\n");
1550 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1551 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1554 if (pdp
->cArgs
&& pdp
->rgvarg
)
1557 for (index
= 0; index
< pdp
->cArgs
; index
++)
1558 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1562 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1564 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1565 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1566 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1567 TRACE("kind:%s\n", typekind_desc
[pty
->typeattr
.typekind
]);
1568 TRACE("fct:%u var:%u impl:%u\n", pty
->typeattr
.cFuncs
, pty
->typeattr
.cVars
, pty
->typeattr
.cImplTypes
);
1569 TRACE("wTypeFlags: 0x%04x\n", pty
->typeattr
.wTypeFlags
);
1570 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1571 if (pty
->typeattr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1573 dump_TLBFuncDesc(pty
->funcdescs
, pty
->typeattr
.cFuncs
);
1574 dump_TLBVarDesc(pty
->vardescs
, pty
->typeattr
.cVars
);
1575 dump_TLBImplType(pty
->impltypes
, pty
->typeattr
.cImplTypes
);
1578 static void dump_VARDESC(const VARDESC
*v
)
1580 MESSAGE("memid %d\n",v
->memid
);
1581 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1582 MESSAGE("oInst %d\n",v
->u
.oInst
);
1583 dump_ELEMDESC(&(v
->elemdescVar
));
1584 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1585 MESSAGE("varkind %d\n",v
->varkind
);
1588 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1590 /* VT_LPWSTR is largest type that, may appear in type description */
1591 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1592 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1593 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1594 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1595 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1596 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1597 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1598 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1601 static void TLB_abort(void)
1606 /* returns the size required for a deep copy of a typedesc into a
1608 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1612 if (alloc_initial_space
)
1613 size
+= sizeof(TYPEDESC
);
1619 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1622 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1623 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1629 /* deep copy a typedesc into a flat buffer */
1630 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1635 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1644 dest
->u
.lptdesc
= buffer
;
1645 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1648 dest
->u
.lpadesc
= buffer
;
1649 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1650 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1651 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1657 /* free custom data allocated by MSFT_CustData */
1658 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1660 TLBCustData
*cd
, *cdn
;
1661 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1663 list_remove(&cd
->entry
);
1664 VariantClear(&cd
->data
);
1669 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1674 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1675 ret
= SysAllocStringLen(NULL
, len
- 1);
1676 if (!ret
) return ret
;
1677 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1681 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1682 UINT n
, MEMBERID memid
)
1685 if(funcdescs
->funcdesc
.memid
== memid
)
1693 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1694 UINT n
, MEMBERID memid
)
1697 if(vardescs
->vardesc
.memid
== memid
)
1705 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1706 UINT n
, const OLECHAR
*name
)
1709 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1717 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1719 TLBCustData
*cust_data
;
1720 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1721 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1726 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1727 UINT n
, const OLECHAR
*name
)
1730 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1738 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1740 list_init(&var_desc
->custdata_list
);
1743 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1747 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1752 TLBVarDesc_Constructor(&ret
[n
-1]);
1759 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1763 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1768 list_init(&ret
[n
-1].custdata_list
);
1775 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1777 list_init(&func_desc
->custdata_list
);
1780 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1784 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1789 TLBFuncDesc_Constructor(&ret
[n
-1]);
1796 static void TLBImplType_Constructor(TLBImplType
*impl
)
1798 list_init(&impl
->custdata_list
);
1801 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1805 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1810 TLBImplType_Constructor(&ret
[n
-1]);
1817 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1818 const GUID
*new_guid
, HREFTYPE hreftype
)
1822 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1823 if (IsEqualGUID(&guid
->guid
, new_guid
))
1827 guid
= heap_alloc(sizeof(TLBGuid
));
1831 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1832 guid
->hreftype
= hreftype
;
1834 list_add_tail(guid_list
, &guid
->entry
);
1839 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1841 TLBCustData
*cust_data
;
1853 return DISP_E_BADVARTYPE
;
1856 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1859 cust_data
= heap_alloc(sizeof(TLBCustData
));
1861 return E_OUTOFMEMORY
;
1863 cust_data
->guid
= tlbguid
;
1864 VariantInit(&cust_data
->data
);
1866 list_add_tail(custdata_list
, &cust_data
->entry
);
1868 VariantClear(&cust_data
->data
);
1870 return VariantCopy(&cust_data
->data
, var
);
1873 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1880 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1881 if (strcmpW(str
->str
, new_str
) == 0)
1885 str
= heap_alloc(sizeof(TLBString
));
1889 str
->str
= SysAllocString(new_str
);
1895 list_add_tail(string_list
, &str
->entry
);
1900 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1901 ULONG
*size
, WORD
*align
)
1907 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1911 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1913 ITypeInfo_Release(other
);
1918 *size
= attr
->cbSizeInstance
;
1920 *align
= attr
->cbAlignment
;
1922 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1923 ITypeInfo_Release(other
);
1928 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1929 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1931 ULONG i
, sub
, ptr_size
;
1934 ptr_size
= get_ptr_size(sys
);
1973 *size
= sizeof(DATE
);
1976 *size
= sizeof(VARIANT
);
1978 if(sys
== SYS_WIN32
)
1979 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1983 *size
= sizeof(DECIMAL
);
1990 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
1991 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
1992 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
1997 case VT_USERDEFINED
:
1998 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2000 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2014 /**********************************************************************
2016 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2019 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2021 if (where
!= DO_NOT_SEEK
)
2023 where
+= pcx
->oStart
;
2024 if (where
> pcx
->length
)
2027 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2035 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2037 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2038 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2040 MSFT_Seek(pcx
, where
);
2041 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2042 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2047 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2052 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2053 FromLEDWords(buffer
, ret
);
2058 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2063 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2064 FromLEWords(buffer
, ret
);
2069 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2072 MSFT_GuidEntry entry
;
2075 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2077 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2080 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2082 guid
= heap_alloc(sizeof(TLBGuid
));
2084 guid
->offset
= offs
;
2085 guid
->guid
= entry
.guid
;
2086 guid
->hreftype
= entry
.hreftype
;
2088 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2090 offs
+= sizeof(MSFT_GuidEntry
);
2094 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2098 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2099 if(ret
->offset
== offset
){
2100 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2108 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2110 MSFT_NameIntro niName
;
2114 ERR_(typelib
)("bad offset %d\n", offset
);
2118 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2119 pcx
->pTblDir
->pNametab
.offset
+offset
);
2121 return niName
.hreftype
;
2124 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2127 MSFT_NameIntro intro
;
2129 int offs
= 0, lengthInChars
;
2131 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2135 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2138 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2139 intro
.namelen
&= 0xFF;
2140 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2142 len_piece
= (len_piece
+ 4) & ~0x3;
2146 string
= heap_alloc(len_piece
+ 1);
2147 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2148 string
[intro
.namelen
] = '\0';
2150 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2151 string
, -1, NULL
, 0);
2152 if (!lengthInChars
) {
2154 return E_UNEXPECTED
;
2157 tlbstr
= heap_alloc(sizeof(TLBString
));
2159 tlbstr
->offset
= offs
;
2160 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2161 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2165 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2171 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2175 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2176 if (tlbstr
->offset
== offset
) {
2177 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2185 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2189 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2190 if (tlbstr
->offset
== offset
) {
2191 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2200 * read a value and fill a VARIANT structure
2202 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2206 TRACE_(typelib
)("\n");
2208 if(offset
<0) { /* data are packed in here */
2209 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2210 V_I4(pVar
) = offset
& 0x3ffffff;
2213 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2214 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2215 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2216 switch (V_VT(pVar
)){
2217 case VT_EMPTY
: /* FIXME: is this right? */
2218 case VT_NULL
: /* FIXME: is this right? */
2219 case VT_I2
: /* this should not happen */
2230 case VT_VOID
: /* FIXME: is this right? */
2238 case VT_DECIMAL
: /* FIXME: is this right? */
2241 /* pointer types with known behaviour */
2244 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2246 V_BSTR(pVar
) = NULL
;
2248 ptr
= heap_alloc_zero(size
);
2249 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2250 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2251 /* FIXME: do we need a AtoW conversion here? */
2252 V_UNION(pVar
, bstrVal
[size
])='\0';
2253 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2258 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2265 case VT_USERDEFINED
:
2271 case VT_STREAMED_OBJECT
:
2272 case VT_STORED_OBJECT
:
2273 case VT_BLOB_OBJECT
:
2278 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2282 if(size
>0) /* (big|small) endian correct? */
2283 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2287 * create a linked list with custom data
2289 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2295 TRACE_(typelib
)("\n");
2297 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2301 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2302 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2303 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2304 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2305 list_add_head(custdata_list
, &pNew
->entry
);
2306 offset
= entry
.next
;
2311 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2314 pTd
->vt
=type
& VT_TYPEMASK
;
2316 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2318 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2321 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2323 return (invkind
== INVOKE_PROPERTYGET
||
2324 invkind
== INVOKE_PROPERTYPUT
||
2325 invkind
== INVOKE_PROPERTYPUTREF
);
2329 MSFT_DoFuncs(TLBContext
* pcx
,
2334 TLBFuncDesc
** pptfd
)
2337 * member information is stored in a data structure at offset
2338 * indicated by the memoffset field of the typeinfo structure
2339 * There are several distinctive parts.
2340 * The first part starts with a field that holds the total length
2341 * of this (first) part excluding this field. Then follow the records,
2342 * for each member there is one record.
2344 * The first entry is always the length of the record (including this
2346 * The rest of the record depends on the type of the member. If there is
2347 * a field indicating the member type (function, variable, interface, etc)
2348 * I have not found it yet. At this time we depend on the information
2349 * in the type info and the usual order how things are stored.
2351 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2354 * Third is an equal sized array with file offsets to the name entry
2357 * The fourth and last (?) part is an array with offsets to the records
2358 * in the first part of this file segment.
2361 int infolen
, nameoffset
, reclength
, i
;
2362 int recoffset
= offset
+ sizeof(INT
);
2364 char *recbuf
= heap_alloc(0xffff);
2365 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2366 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2368 TRACE_(typelib
)("\n");
2370 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2372 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2374 for ( i
= 0; i
< cFuncs
; i
++ )
2378 /* name, eventually add to a hash table */
2379 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2380 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2382 /* read the function information record */
2383 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2385 reclength
&= 0xffff;
2387 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2389 /* size without argument data */
2390 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2391 if (pFuncRec
->FKCCIC
& 0x1000)
2392 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2394 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2395 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2397 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2398 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2400 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2402 if (pFuncRec
->FKCCIC
& 0x2000 )
2404 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2405 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2406 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2409 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2412 ptfd
->Entry
= (TLBString
*)-1;
2414 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2415 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2417 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2418 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2420 /* fill the FuncDesc Structure */
2421 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2422 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2424 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2425 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2426 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2427 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2428 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2429 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2430 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2432 /* nameoffset is sometimes -1 on the second half of a propget/propput
2433 * pair of functions */
2434 if ((nameoffset
== -1) && (i
> 0) &&
2435 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2436 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2437 ptfd
->Name
= ptfd_prev
->Name
;
2439 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2443 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2445 /* do the parameters/arguments */
2446 if(pFuncRec
->nrargs
)
2449 MSFT_ParameterInfo paraminfo
;
2451 ptfd
->funcdesc
.lprgelemdescParam
=
2452 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2454 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2456 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2457 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2459 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2461 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2467 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2470 if (paraminfo
.oName
!= -1)
2471 ptfd
->pParamDesc
[j
].Name
=
2472 MSFT_ReadName( pcx
, paraminfo
.oName
);
2473 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2476 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2477 (pFuncRec
->FKCCIC
& 0x1000) )
2479 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2481 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2483 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2485 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2486 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2488 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2492 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2495 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2496 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2497 pFuncRec
->FKCCIC
& 0x80 )
2500 pFuncRec
->oArgCustData
[j
],
2501 &ptfd
->pParamDesc
[j
].custdata_list
);
2504 /* SEEK value = jump to offset,
2505 * from there jump to the end of record,
2506 * go back by (j-1) arguments
2508 MSFT_ReadLEDWords( ¶minfo
,
2509 sizeof(MSFT_ParameterInfo
), pcx
,
2510 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2511 * sizeof(MSFT_ParameterInfo
)));
2515 /* scode is not used: archaic win16 stuff FIXME: right? */
2516 ptfd
->funcdesc
.cScodes
= 0 ;
2517 ptfd
->funcdesc
.lprgscode
= NULL
;
2521 recoffset
+= reclength
;
2526 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2527 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2529 int infolen
, nameoffset
, reclength
;
2531 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2536 TRACE_(typelib
)("\n");
2538 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2539 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2540 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2541 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2542 recoffset
+= offset
+sizeof(INT
);
2543 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2544 /* name, eventually add to a hash table */
2545 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2546 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2547 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2548 /* read the variable information record */
2549 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2551 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2554 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2555 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2557 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2558 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2560 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2561 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2563 /* fill the VarDesc Structure */
2564 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2565 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2566 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2567 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2568 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2569 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2570 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2571 if(pVarRec
->VarKind
== VAR_CONST
){
2572 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2573 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2574 pVarRec
->OffsValue
, pcx
);
2576 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2577 recoffset
+= reclength
;
2581 /* process Implemented Interfaces of a com class */
2582 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2586 MSFT_RefRecord refrec
;
2589 TRACE_(typelib
)("\n");
2591 pTI
->impltypes
= TLBImplType_Alloc(count
);
2592 pImpl
= pTI
->impltypes
;
2593 for(i
=0;i
<count
;i
++){
2594 if(offset
<0) break; /* paranoia */
2595 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2596 pImpl
->hRef
= refrec
.reftype
;
2597 pImpl
->implflags
=refrec
.flags
;
2598 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2599 offset
=refrec
.onext
;
2605 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2606 * and some structures, and fix the alignment */
2607 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2609 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2610 switch(info
->tdescAlias
->vt
){
2618 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2619 info
->typeattr
.cbAlignment
= sizeof(void*);
2622 case VT_USERDEFINED
:
2623 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2626 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2627 info
->typeattr
.cbAlignment
= 8;
2629 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2630 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2632 info
->typeattr
.cbAlignment
= sizeof(void*);
2635 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2636 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2637 info
->typeattr
.typekind
== TKIND_COCLASS
){
2638 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2639 info
->typeattr
.cbAlignment
= sizeof(void*);
2645 * process a typeinfo record
2647 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2650 ITypeLibImpl
* pLibInfo
)
2652 MSFT_TypeInfoBase tiBase
;
2653 ITypeInfoImpl
*ptiRet
;
2655 TRACE_(typelib
)("count=%u\n", count
);
2657 ptiRet
= ITypeInfoImpl_Constructor();
2658 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2659 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2661 /* this is where we are coming from */
2662 ptiRet
->pTypeLib
= pLibInfo
;
2663 ptiRet
->index
=count
;
2665 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2666 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2667 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2668 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2669 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2670 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2671 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2672 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2673 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2674 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2675 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2676 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2677 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2678 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2680 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2681 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2682 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2686 /* IDLDESC idldescType; *//* never saw this one != zero */
2688 /* name, eventually add to a hash table */
2689 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2690 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2691 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2693 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2694 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2695 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2697 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2698 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2700 /* note: InfoType's Help file and HelpStringDll come from the containing
2701 * library. Further HelpString and Docstring appear to be the same thing :(
2704 if(ptiRet
->typeattr
.cFuncs
>0 )
2705 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2706 ptiRet
->typeattr
.cVars
,
2707 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2709 if(ptiRet
->typeattr
.cVars
>0 )
2710 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2711 ptiRet
->typeattr
.cVars
,
2712 tiBase
.memoffset
, &ptiRet
->vardescs
);
2713 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2714 switch(ptiRet
->typeattr
.typekind
)
2717 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2720 case TKIND_DISPATCH
:
2721 /* This is not -1 when the interface is a non-base dual interface or
2722 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2723 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2727 if (tiBase
.datatype1
!= -1)
2729 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2730 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2734 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2735 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2739 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2741 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2742 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2743 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2744 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2745 if (TRACE_ON(typelib
))
2746 dump_TypeInfo(ptiRet
);
2751 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2754 INT16 len_str
, len_piece
;
2755 int offs
= 0, lengthInChars
;
2757 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2761 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2764 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2765 len_piece
= len_str
+ sizeof(INT16
);
2767 len_piece
= (len_piece
+ 4) & ~0x3;
2771 string
= heap_alloc(len_piece
+ 1);
2772 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2773 string
[len_str
] = '\0';
2775 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2776 string
, -1, NULL
, 0);
2777 if (!lengthInChars
) {
2779 return E_UNEXPECTED
;
2782 tlbstr
= heap_alloc(sizeof(TLBString
));
2784 tlbstr
->offset
= offs
;
2785 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2786 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2790 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2796 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2801 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2802 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2803 MSFT_ImpInfo impinfo
;
2806 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2808 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2809 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2811 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2812 if(pImpLib
->offset
==impinfo
.oImpFile
)
2815 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2816 ref
->reference
= offs
;
2817 ref
->pImpTLInfo
= pImpLib
;
2818 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2819 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2820 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2821 ref
->index
= TLB_REF_USE_GUID
;
2823 ref
->index
= impinfo
.oGuid
;
2825 ERR("Cannot find a reference\n");
2826 ref
->reference
= -1;
2827 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2830 offs
+= sizeof(impinfo
);
2836 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2837 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2838 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2841 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2842 static CRITICAL_SECTION cache_section
;
2843 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2845 0, 0, &cache_section
,
2846 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2847 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2849 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2852 typedef struct TLB_PEFile
2854 IUnknown IUnknown_iface
;
2857 HRSRC typelib_resource
;
2858 HGLOBAL typelib_global
;
2859 LPVOID typelib_base
;
2862 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2864 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2867 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2869 if (IsEqualIID(riid
, &IID_IUnknown
))
2872 IUnknown_AddRef(iface
);
2876 return E_NOINTERFACE
;
2879 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2881 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2882 return InterlockedIncrement(&This
->refs
);
2885 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2887 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2888 ULONG refs
= InterlockedDecrement(&This
->refs
);
2891 if (This
->typelib_global
)
2892 FreeResource(This
->typelib_global
);
2894 FreeLibrary(This
->dll
);
2900 static const IUnknownVtbl TLB_PEFile_Vtable
=
2902 TLB_PEFile_QueryInterface
,
2907 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2910 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2912 This
= heap_alloc(sizeof(TLB_PEFile
));
2914 return E_OUTOFMEMORY
;
2916 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2919 This
->typelib_resource
= NULL
;
2920 This
->typelib_global
= NULL
;
2921 This
->typelib_base
= NULL
;
2923 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2924 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2928 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2929 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2930 if (This
->typelib_resource
)
2932 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2933 if (This
->typelib_global
)
2935 This
->typelib_base
= LockResource(This
->typelib_global
);
2937 if (This
->typelib_base
)
2939 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2940 *ppBase
= This
->typelib_base
;
2941 *ppFile
= &This
->IUnknown_iface
;
2947 TRACE("No TYPELIB resource found\n");
2951 TLB_PEFile_Release(&This
->IUnknown_iface
);
2955 typedef struct TLB_NEFile
2957 IUnknown IUnknown_iface
;
2959 LPVOID typelib_base
;
2962 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2964 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2967 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2969 if (IsEqualIID(riid
, &IID_IUnknown
))
2972 IUnknown_AddRef(iface
);
2976 return E_NOINTERFACE
;
2979 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2981 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2982 return InterlockedIncrement(&This
->refs
);
2985 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2987 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2988 ULONG refs
= InterlockedDecrement(&This
->refs
);
2991 heap_free(This
->typelib_base
);
2997 static const IUnknownVtbl TLB_NEFile_Vtable
=
2999 TLB_NEFile_QueryInterface
,
3004 /***********************************************************************
3005 * read_xx_header [internal]
3007 static int read_xx_header( HFILE lzfd
)
3009 IMAGE_DOS_HEADER mzh
;
3012 LZSeek( lzfd
, 0, SEEK_SET
);
3013 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3015 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3018 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3019 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3022 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3024 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3025 return IMAGE_OS2_SIGNATURE
;
3026 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3027 return IMAGE_NT_SIGNATURE
;
3030 WARN("Can't handle %s files.\n", magic
);
3035 /***********************************************************************
3036 * find_ne_resource [internal]
3038 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3039 DWORD
*resLen
, DWORD
*resOff
)
3041 IMAGE_OS2_HEADER nehd
;
3042 NE_TYPEINFO
*typeInfo
;
3043 NE_NAMEINFO
*nameInfo
;
3049 /* Read in NE header */
3050 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3051 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3053 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3056 TRACE("No resources in NE dll\n" );
3060 /* Read in resource table */
3061 resTab
= heap_alloc( resTabSize
);
3062 if ( !resTab
) return FALSE
;
3064 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3065 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3067 heap_free( resTab
);
3072 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3074 if (!IS_INTRESOURCE(typeid)) /* named type */
3076 BYTE len
= strlen( typeid );
3077 while (typeInfo
->type_id
)
3079 if (!(typeInfo
->type_id
& 0x8000))
3081 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3082 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
3084 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3085 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3088 else /* numeric type id */
3090 WORD id
= LOWORD(typeid) | 0x8000;
3091 while (typeInfo
->type_id
)
3093 if (typeInfo
->type_id
== id
) goto found_type
;
3094 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3095 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3098 TRACE("No typeid entry found for %p\n", typeid );
3099 heap_free( resTab
);
3103 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3105 if (!IS_INTRESOURCE(resid
)) /* named resource */
3107 BYTE len
= strlen( resid
);
3108 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3110 BYTE
*p
= resTab
+ nameInfo
->id
;
3111 if (nameInfo
->id
& 0x8000) continue;
3112 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3115 else /* numeric resource id */
3117 WORD id
= LOWORD(resid
) | 0x8000;
3118 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3119 if (nameInfo
->id
== id
) goto found_name
;
3121 TRACE("No resid entry found for %p\n", typeid );
3122 heap_free( resTab
);
3126 /* Return resource data */
3127 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3128 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3130 heap_free( resTab
);
3134 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3138 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3141 This
= heap_alloc(sizeof(TLB_NEFile
));
3142 if (!This
) return E_OUTOFMEMORY
;
3144 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3146 This
->typelib_base
= NULL
;
3148 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3149 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3151 DWORD reslen
, offset
;
3152 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3154 This
->typelib_base
= heap_alloc(reslen
);
3155 if( !This
->typelib_base
)
3159 LZSeek( lzfd
, offset
, SEEK_SET
);
3160 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3162 *ppBase
= This
->typelib_base
;
3163 *pdwTLBLength
= reslen
;
3164 *ppFile
= &This
->IUnknown_iface
;
3170 if( lzfd
>= 0) LZClose( lzfd
);
3171 TLB_NEFile_Release(&This
->IUnknown_iface
);
3175 typedef struct TLB_Mapping
3177 IUnknown IUnknown_iface
;
3181 LPVOID typelib_base
;
3184 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3186 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3189 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3191 if (IsEqualIID(riid
, &IID_IUnknown
))
3194 IUnknown_AddRef(iface
);
3198 return E_NOINTERFACE
;
3201 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3203 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3204 return InterlockedIncrement(&This
->refs
);
3207 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3209 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3210 ULONG refs
= InterlockedDecrement(&This
->refs
);
3213 if (This
->typelib_base
)
3214 UnmapViewOfFile(This
->typelib_base
);
3216 CloseHandle(This
->mapping
);
3217 if (This
->file
!= INVALID_HANDLE_VALUE
)
3218 CloseHandle(This
->file
);
3224 static const IUnknownVtbl TLB_Mapping_Vtable
=
3226 TLB_Mapping_QueryInterface
,
3231 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3235 This
= heap_alloc(sizeof(TLB_Mapping
));
3237 return E_OUTOFMEMORY
;
3239 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3241 This
->file
= INVALID_HANDLE_VALUE
;
3242 This
->mapping
= NULL
;
3243 This
->typelib_base
= NULL
;
3245 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3246 if (INVALID_HANDLE_VALUE
!= This
->file
)
3248 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3251 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3252 if(This
->typelib_base
)
3254 /* retrieve file size */
3255 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3256 *ppBase
= This
->typelib_base
;
3257 *ppFile
= &This
->IUnknown_iface
;
3263 IUnknown_Release(&This
->IUnknown_iface
);
3264 return TYPE_E_CANTLOADLIBRARY
;
3267 /****************************************************************************
3270 * find the type of the typelib file and map the typelib resource into
3274 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3275 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3277 ITypeLibImpl
*entry
;
3280 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3281 LPVOID pBase
= NULL
;
3282 DWORD dwTLBLength
= 0;
3283 IUnknown
*pFile
= NULL
;
3288 index_str
= strrchrW(pszFileName
, '\\');
3289 if(index_str
&& *++index_str
!= '\0')
3292 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3293 if(*end_ptr
== '\0')
3295 int str_len
= index_str
- pszFileName
- 1;
3297 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3298 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3303 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3305 if(strchrW(file
, '\\'))
3307 lstrcpyW(pszPath
, file
);
3311 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3312 pszPath
[len
] = '\\';
3313 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3317 if(file
!= pszFileName
) heap_free(file
);
3319 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3320 if(h
!= INVALID_HANDLE_VALUE
){
3321 FILE_NAME_INFORMATION size_info
;
3324 /* GetFileInformationByHandleEx returns the path of the file without
3325 * WOW64 redirection */
3326 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, &size_info
, sizeof(size_info
));
3327 if(br
|| GetLastError() == ERROR_MORE_DATA
){
3328 FILE_NAME_INFORMATION
*info
;
3329 DWORD size
= sizeof(*info
) + size_info
.FileNameLength
+ sizeof(WCHAR
);
3331 info
= HeapAlloc(GetProcessHeap(), 0, size
);
3333 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, info
, size
);
3335 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3336 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3339 HeapFree(GetProcessHeap(), 0, info
);
3345 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3347 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3348 EnterCriticalSection(&cache_section
);
3349 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3351 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3353 TRACE("cache hit\n");
3354 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3355 ITypeLib2_AddRef(*ppTypeLib
);
3356 LeaveCriticalSection(&cache_section
);
3360 LeaveCriticalSection(&cache_section
);
3362 /* now actually load and parse the typelib */
3364 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3365 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3366 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3367 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3368 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3371 if (dwTLBLength
>= 4)
3373 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3374 if (dwSignature
== MSFT_SIGNATURE
)
3375 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3376 else if (dwSignature
== SLTG_SIGNATURE
)
3377 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3380 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3381 ret
= TYPE_E_CANTLOADLIBRARY
;
3385 ret
= TYPE_E_CANTLOADLIBRARY
;
3386 IUnknown_Release(pFile
);
3390 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3392 TRACE("adding to cache\n");
3393 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3394 lstrcpyW(impl
->path
, pszPath
);
3395 /* We should really canonicalise the path here. */
3396 impl
->index
= index
;
3398 /* FIXME: check if it has added already in the meantime */
3399 EnterCriticalSection(&cache_section
);
3400 list_add_head(&tlb_cache
, &impl
->entry
);
3401 LeaveCriticalSection(&cache_section
);
3407 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3409 ret
= TYPE_E_CANTLOADLIBRARY
;
3416 /*================== ITypeLib(2) Methods ===================================*/
3418 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3420 ITypeLibImpl
* pTypeLibImpl
;
3422 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3423 if (!pTypeLibImpl
) return NULL
;
3425 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3426 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3427 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3428 pTypeLibImpl
->ref
= 1;
3430 list_init(&pTypeLibImpl
->implib_list
);
3431 list_init(&pTypeLibImpl
->custdata_list
);
3432 list_init(&pTypeLibImpl
->name_list
);
3433 list_init(&pTypeLibImpl
->string_list
);
3434 list_init(&pTypeLibImpl
->guid_list
);
3435 list_init(&pTypeLibImpl
->ref_list
);
3436 pTypeLibImpl
->dispatch_href
= -1;
3438 return pTypeLibImpl
;
3441 /****************************************************************************
3442 * ITypeLib2_Constructor_MSFT
3444 * loading an MSFT typelib from an in-memory image
3446 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3450 MSFT_Header tlbHeader
;
3451 MSFT_SegDir tlbSegDir
;
3452 ITypeLibImpl
* pTypeLibImpl
;
3455 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3457 pTypeLibImpl
= TypeLibImpl_Constructor();
3458 if (!pTypeLibImpl
) return NULL
;
3460 /* get pointer to beginning of typelib data */
3464 cx
.pLibInfo
= pTypeLibImpl
;
3465 cx
.length
= dwTLBLength
;
3468 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3469 TRACE_(typelib
)("header:\n");
3470 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3471 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3472 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3475 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3477 /* there is a small amount of information here until the next important
3479 * the segment directory . Try to calculate the amount of data */
3480 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3482 /* now read the segment directory */
3483 TRACE("read segment directory (at %d)\n",lPSegDir
);
3484 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3485 cx
.pTblDir
= &tlbSegDir
;
3487 /* just check two entries */
3488 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3490 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3491 heap_free(pTypeLibImpl
);
3495 MSFT_ReadAllNames(&cx
);
3496 MSFT_ReadAllStrings(&cx
);
3497 MSFT_ReadAllGuids(&cx
);
3499 /* now fill our internal data */
3500 /* TLIBATTR fields */
3501 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3503 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3504 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3505 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3506 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3507 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3509 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3510 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3512 /* name, eventually add to a hash table */
3513 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3516 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3517 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3519 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3522 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3523 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3526 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3529 if(tlbHeader
.CustomDataOffset
>= 0)
3531 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3534 /* fill in type descriptions */
3535 if(tlbSegDir
.pTypdescTab
.length
> 0)
3537 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3539 pTypeLibImpl
->ctTypeDesc
= cTD
;
3540 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3541 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3544 /* FIXME: add several sanity checks here */
3545 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3546 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3548 /* FIXME: check safearray */
3550 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3552 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3554 else if(td
[0] == VT_CARRAY
)
3556 /* array descr table here */
3557 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3559 else if(td
[0] == VT_USERDEFINED
)
3561 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3563 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3566 /* second time around to fill the array subscript info */
3569 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3570 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3572 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3573 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3576 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3578 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3580 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3582 for(j
= 0; j
<td
[2]; j
++)
3584 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3585 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3586 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3587 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3592 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3593 ERR("didn't find array description data\n");
3598 /* imported type libs */
3599 if(tlbSegDir
.pImpFiles
.offset
>0)
3602 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3605 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3609 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3610 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3611 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3613 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3614 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3615 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3616 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3619 name
= heap_alloc_zero(size
+1);
3620 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3621 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3624 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3625 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3627 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3631 MSFT_ReadAllRefs(&cx
);
3633 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3636 if(tlbHeader
.nrtypeinfos
>= 0 )
3638 ITypeInfoImpl
**ppTI
;
3640 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3642 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3644 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3647 (pTypeLibImpl
->TypeInfoCount
)++;
3652 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3653 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3654 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3658 TRACE("(%p)\n", pTypeLibImpl
);
3659 return &pTypeLibImpl
->ITypeLib2_iface
;
3663 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3669 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3670 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3674 guid
->Data4
[0] = s
>> 8;
3675 guid
->Data4
[1] = s
& 0xff;
3678 for(i
= 0; i
< 6; i
++) {
3679 memcpy(b
, str
+ 24 + 2 * i
, 2);
3680 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3685 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3692 bytelen
= *(const WORD
*)ptr
;
3693 if(bytelen
== 0xffff) return 2;
3695 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3696 tmp_str
= SysAllocStringLen(NULL
, len
);
3698 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3699 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3700 SysFreeString(tmp_str
);
3705 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3710 bytelen
= *(const WORD
*)ptr
;
3711 if(bytelen
== 0xffff) return 2;
3712 *str
= heap_alloc(bytelen
+ 1);
3713 memcpy(*str
, ptr
+ 2, bytelen
);
3714 (*str
)[bytelen
] = '\0';
3718 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3723 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3724 if (tlbstr
->offset
== offset
)
3728 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3729 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3730 SysFreeString(tmp_str
);
3735 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3737 char *ptr
= pLibBlk
;
3740 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3741 FIXME("libblk magic = %04x\n", w
);
3746 if((w
= *(WORD
*)ptr
) != 0xffff) {
3747 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3752 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3754 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3756 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3759 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3760 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3763 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3764 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3766 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3769 ptr
+= 4; /* skip res12 */
3771 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3774 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3777 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3780 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3781 ptr
+= sizeof(GUID
);
3783 return ptr
- (char*)pLibBlk
;
3786 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3791 } sltg_ref_lookup_t
;
3793 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3794 HREFTYPE
*typelib_ref
)
3796 if(table
&& typeinfo_ref
< table
->num
)
3798 *typelib_ref
= table
->refs
[typeinfo_ref
];
3802 ERR_(typelib
)("Unable to find reference\n");
3807 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3812 if((*pType
& 0xe00) == 0xe00) {
3814 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3815 pTD
= pTD
->u
.lptdesc
;
3817 switch(*pType
& 0x3f) {
3820 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3821 pTD
= pTD
->u
.lptdesc
;
3824 case VT_USERDEFINED
:
3825 pTD
->vt
= VT_USERDEFINED
;
3826 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3832 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3835 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3837 pTD
->vt
= VT_CARRAY
;
3838 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3839 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3840 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3841 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3843 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3849 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3853 pTD
->vt
= VT_SAFEARRAY
;
3854 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3855 pTD
= pTD
->u
.lptdesc
;
3859 pTD
->vt
= *pType
& 0x3f;
3868 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3869 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3871 /* Handle [in/out] first */
3872 if((*pType
& 0xc000) == 0xc000)
3873 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3874 else if(*pType
& 0x8000)
3875 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3876 else if(*pType
& 0x4000)
3877 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3879 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3882 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3885 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3887 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3891 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3896 TLBRefType
*ref_type
;
3897 sltg_ref_lookup_t
*table
;
3898 HREFTYPE typelib_ref
;
3900 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3901 FIXME("Ref magic = %x\n", pRef
->magic
);
3904 name
= ( (char*)pRef
->names
+ pRef
->number
);
3906 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3907 table
->num
= pRef
->number
>> 3;
3909 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3911 /* We don't want the first href to be 0 */
3912 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3914 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3916 unsigned int lib_offs
, type_num
;
3918 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3920 name
+= SLTG_ReadStringA(name
, &refname
);
3921 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3922 FIXME_(typelib
)("Can't sscanf ref\n");
3923 if(lib_offs
!= 0xffff) {
3926 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3927 if(import
->offset
== lib_offs
)
3930 if(&import
->entry
== &pTL
->implib_list
) {
3931 char fname
[MAX_PATH
+1];
3935 import
= heap_alloc_zero(sizeof(*import
));
3936 import
->offset
= lib_offs
;
3937 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3938 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3939 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3940 &import
->wVersionMajor
,
3941 &import
->wVersionMinor
,
3942 &import
->lcid
, fname
) != 4) {
3943 FIXME_(typelib
)("can't sscanf ref %s\n",
3944 pNameTable
+ lib_offs
+ 40);
3946 len
= strlen(fname
);
3947 if(fname
[len
-1] != '#')
3948 FIXME("fname = %s\n", fname
);
3949 fname
[len
-1] = '\0';
3950 import
->name
= TLB_MultiByteToBSTR(fname
);
3951 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3953 ref_type
->pImpTLInfo
= import
;
3955 /* Store a reference to IDispatch */
3956 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3957 pTL
->dispatch_href
= typelib_ref
;
3959 } else { /* internal ref */
3960 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3962 ref_type
->reference
= typelib_ref
;
3963 ref_type
->index
= type_num
;
3966 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3968 table
->refs
[ref
] = typelib_ref
;
3971 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3972 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3973 dump_TLBRefType(pTL
);
3977 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3978 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3980 SLTG_ImplInfo
*info
;
3981 TLBImplType
*pImplType
;
3982 /* I don't really get this structure, usually it's 0x16 bytes
3983 long, but iuser.tlb contains some that are 0x18 bytes long.
3984 That's ok because we can use the next ptr to jump to the next
3985 one. But how do we know the length of the last one? The WORD
3986 at offs 0x8 might be the clue. For now I'm just assuming that
3987 the last one is the regular 0x16 bytes. */
3989 info
= (SLTG_ImplInfo
*)pBlk
;
3991 pTI
->typeattr
.cImplTypes
++;
3992 if(info
->next
== 0xffff)
3994 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3997 info
= (SLTG_ImplInfo
*)pBlk
;
3998 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
3999 pImplType
= pTI
->impltypes
;
4001 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4002 pImplType
->implflags
= info
->impltypeflags
;
4005 if(info
->next
== 0xffff)
4008 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4009 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4011 info
++; /* see comment at top of function */
4015 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4016 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4018 TLBVarDesc
*pVarDesc
;
4019 const TLBString
*prevName
= NULL
;
4020 SLTG_Variable
*pItem
;
4024 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4026 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4027 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4029 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4031 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4032 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4033 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4037 if (pItem
->name
== 0xfffe)
4038 pVarDesc
->Name
= prevName
;
4040 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4042 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4043 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4044 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4046 if(pItem
->flags
& 0x02)
4047 pType
= &pItem
->type
;
4049 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4051 if (pItem
->flags
& ~0xda)
4052 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4054 SLTG_DoElem(pType
, pBlk
,
4055 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4057 if (TRACE_ON(typelib
)) {
4059 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4060 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4063 if (pItem
->flags
& 0x40) {
4064 TRACE_(typelib
)("VAR_DISPATCH\n");
4065 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4067 else if (pItem
->flags
& 0x10) {
4068 TRACE_(typelib
)("VAR_CONST\n");
4069 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4070 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4071 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4072 if (pItem
->flags
& 0x08)
4073 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4075 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4081 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4083 TRACE_(typelib
)("len = %u\n", len
);
4084 if (len
== 0xffff) {
4087 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4088 str
= SysAllocStringLen(NULL
, alloc_len
);
4089 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4091 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4092 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4101 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4102 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4105 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4110 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4111 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4112 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4115 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4116 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4118 if (pItem
->flags
& 0x80)
4119 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4121 prevName
= pVarDesc
->Name
;
4123 pTI
->typeattr
.cVars
= cVars
;
4126 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4127 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4129 SLTG_Function
*pFunc
;
4131 TLBFuncDesc
*pFuncDesc
;
4133 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4135 pFuncDesc
= pTI
->funcdescs
;
4136 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4137 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4142 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4143 case SLTG_FUNCTION_MAGIC
:
4144 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4146 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4147 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4149 case SLTG_STATIC_FUNCTION_MAGIC
:
4150 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4153 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4156 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4158 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4159 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4160 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4161 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4162 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4163 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4165 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4166 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4168 if(pFunc
->retnextopt
& 0x80)
4169 pType
= &pFunc
->rettype
;
4171 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4173 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4175 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4176 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4177 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4179 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4181 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4182 char *paramName
= pNameTable
+ *pArg
;
4184 /* If arg type follows then paramName points to the 2nd
4185 letter of the name, else the next WORD is an offset to
4186 the arg type and paramName points to the first letter.
4187 So let's take one char off paramName and see if we're
4188 pointing at an alpha-numeric char. However if *pArg is
4189 0xffff or 0xfffe then the param has no name, the former
4190 meaning that the next WORD is the type, the latter
4191 meaning that the next WORD is an offset to the type. */
4196 else if(*pArg
== 0xfffe) {
4200 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4205 if(HaveOffs
) { /* the next word is an offset to type */
4206 pType
= (WORD
*)(pBlk
+ *pArg
);
4207 SLTG_DoElem(pType
, pBlk
,
4208 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4213 pArg
= SLTG_DoElem(pArg
, pBlk
,
4214 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4217 /* Are we an optional param ? */
4218 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4219 pFuncDesc
->funcdesc
.cParamsOpt
)
4220 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4223 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4224 paramName
- pNameTable
, pTI
->pTypeLib
);
4226 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4230 pTI
->typeattr
.cFuncs
= cFuncs
;
4233 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4234 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4235 SLTG_TypeInfoTail
*pTITail
)
4238 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4240 if(pTIHeader
->href_table
!= 0xffffffff) {
4241 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4247 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4248 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4250 heap_free(ref_lookup
);
4254 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4255 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4256 const SLTG_TypeInfoTail
*pTITail
)
4259 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4261 if(pTIHeader
->href_table
!= 0xffffffff) {
4262 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4268 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4269 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4272 if (pTITail
->funcs_off
!= 0xffff)
4273 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4275 heap_free(ref_lookup
);
4277 if (TRACE_ON(typelib
))
4278 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4281 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4282 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4283 const SLTG_TypeInfoTail
*pTITail
)
4285 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4288 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4289 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4290 const SLTG_TypeInfoTail
*pTITail
)
4293 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4295 if (pTITail
->simple_alias
) {
4296 /* if simple alias, no more processing required */
4297 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4298 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4302 if(pTIHeader
->href_table
!= 0xffffffff) {
4303 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4307 /* otherwise it is an offset to a type */
4308 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4310 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4311 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4313 heap_free(ref_lookup
);
4316 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4317 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4318 const SLTG_TypeInfoTail
*pTITail
)
4320 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4321 if (pTIHeader
->href_table
!= 0xffffffff)
4322 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4325 if (pTITail
->vars_off
!= 0xffff)
4326 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4328 if (pTITail
->funcs_off
!= 0xffff)
4329 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4331 if (pTITail
->impls_off
!= 0xffff)
4332 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4334 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4335 * of dispinterface functions including the IDispatch ones, so
4336 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4337 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4339 heap_free(ref_lookup
);
4340 if (TRACE_ON(typelib
))
4341 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4344 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4345 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4346 const SLTG_TypeInfoTail
*pTITail
)
4348 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4351 static void SLTG_ProcessModule(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
);
4365 heap_free(ref_lookup
);
4366 if (TRACE_ON(typelib
))
4370 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4371 manageable copy of it into this */
4384 } SLTG_InternalOtherTypeInfo
;
4386 /****************************************************************************
4387 * ITypeLib2_Constructor_SLTG
4389 * loading a SLTG typelib from an in-memory image
4391 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4393 ITypeLibImpl
*pTypeLibImpl
;
4394 SLTG_Header
*pHeader
;
4395 SLTG_BlkEntry
*pBlkEntry
;
4399 LPVOID pBlk
, pFirstBlk
;
4400 SLTG_LibBlk
*pLibBlk
;
4401 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4402 char *pAfterOTIBlks
= NULL
;
4403 char *pNameTable
, *ptr
;
4406 ITypeInfoImpl
**ppTypeInfoImpl
;
4408 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4411 pTypeLibImpl
= TypeLibImpl_Constructor();
4412 if (!pTypeLibImpl
) return NULL
;
4416 TRACE_(typelib
)("header:\n");
4417 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4418 pHeader
->nrOfFileBlks
);
4419 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4420 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4421 pHeader
->SLTG_magic
);
4425 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4426 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4428 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4429 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4431 /* Next we have a magic block */
4432 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4434 /* Let's see if we're still in sync */
4435 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4436 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4437 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4440 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4441 sizeof(SLTG_DIR_MAGIC
))) {
4442 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4446 pIndex
= (SLTG_Index
*)(pMagic
+1);
4448 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4450 pFirstBlk
= pPad9
+ 1;
4452 /* We'll set up a ptr to the main library block, which is the last one. */
4454 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4455 pBlkEntry
[order
].next
!= 0;
4456 order
= pBlkEntry
[order
].next
- 1) {
4457 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4461 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4463 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4468 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4470 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4473 ptr
= (char*)pLibBlk
+ len
;
4475 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4479 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4481 w
= *(WORD
*)(ptr
+ 2);
4484 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4485 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4486 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4488 w
= *(WORD
*)(ptr
+ 4 + len
);
4490 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4492 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4493 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4494 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4496 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4497 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4498 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4500 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4501 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4504 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4505 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4506 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4507 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4508 len
+= sizeof(SLTG_OtherTypeInfo
);
4512 pAfterOTIBlks
= ptr
;
4514 /* Skip this WORD and get the next DWORD */
4515 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4517 /* Now add this to pLibBLk look at what we're pointing at and
4518 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4519 dust and we should be pointing at the beginning of the name
4522 pNameTable
= (char*)pLibBlk
+ len
;
4524 switch(*(WORD
*)pNameTable
) {
4531 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4535 pNameTable
+= 0x216;
4539 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4541 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4544 /* Hopefully we now have enough ptrs set up to actually read in
4545 some TypeInfos. It's not clear which order to do them in, so
4546 I'll just follow the links along the BlkEntry chain and read
4547 them in the order in which they are in the file */
4549 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4550 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4552 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4553 pBlkEntry
[order
].next
!= 0;
4554 order
= pBlkEntry
[order
].next
- 1, i
++) {
4556 SLTG_TypeInfoHeader
*pTIHeader
;
4557 SLTG_TypeInfoTail
*pTITail
;
4558 SLTG_MemberHeader
*pMemHeader
;
4560 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4561 FIXME_(typelib
)("Index strings don't match\n");
4562 heap_free(pOtherTypeInfoBlks
);
4567 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4568 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4569 heap_free(pOtherTypeInfoBlks
);
4572 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4573 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4574 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4576 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4577 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4578 (*ppTypeInfoImpl
)->index
= i
;
4579 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4580 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4581 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4582 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4583 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4584 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4585 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4586 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4588 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4589 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4591 if((pTIHeader
->typeflags1
& 7) != 2)
4592 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4593 if(pTIHeader
->typeflags3
!= 2)
4594 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4596 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4597 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4598 typekind_desc
[pTIHeader
->typekind
],
4599 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4600 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4602 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4604 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4606 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4607 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4608 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4610 switch(pTIHeader
->typekind
) {
4612 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4613 pTIHeader
, pTITail
);
4617 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4618 pTIHeader
, pTITail
);
4621 case TKIND_INTERFACE
:
4622 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4623 pTIHeader
, pTITail
);
4627 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4628 pTIHeader
, pTITail
);
4632 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4633 pTIHeader
, pTITail
);
4636 case TKIND_DISPATCH
:
4637 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4638 pTIHeader
, pTITail
);
4642 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4643 pTIHeader
, pTITail
);
4647 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4652 /* could get cFuncs, cVars and cImplTypes from here
4653 but we've already set those */
4654 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4670 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4673 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4674 FIXME("Somehow processed %d TypeInfos\n", i
);
4675 heap_free(pOtherTypeInfoBlks
);
4679 heap_free(pOtherTypeInfoBlks
);
4680 return &pTypeLibImpl
->ITypeLib2_iface
;
4683 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4685 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4687 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4689 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4690 IsEqualIID(riid
,&IID_ITypeLib
)||
4691 IsEqualIID(riid
,&IID_ITypeLib2
))
4693 *ppv
= &This
->ITypeLib2_iface
;
4695 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4696 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4698 *ppv
= &This
->ICreateTypeLib2_iface
;
4703 TRACE("-- Interface: E_NOINTERFACE\n");
4704 return E_NOINTERFACE
;
4707 IUnknown_AddRef((IUnknown
*)*ppv
);
4711 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4713 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4714 ULONG ref
= InterlockedIncrement(&This
->ref
);
4716 TRACE("(%p) ref=%u\n", This
, ref
);
4721 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4723 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4724 ULONG ref
= InterlockedDecrement(&This
->ref
);
4726 TRACE("(%p) ref=%u\n",This
, ref
);
4730 TLBImpLib
*pImpLib
, *pImpLibNext
;
4731 TLBRefType
*ref_type
, *ref_type_next
;
4732 TLBString
*tlbstr
, *tlbstr_next
;
4733 TLBGuid
*tlbguid
, *tlbguid_next
;
4736 /* remove cache entry */
4739 TRACE("removing from cache list\n");
4740 EnterCriticalSection(&cache_section
);
4741 if(This
->entry
.next
)
4742 list_remove(&This
->entry
);
4743 LeaveCriticalSection(&cache_section
);
4744 heap_free(This
->path
);
4746 TRACE(" destroying ITypeLib(%p)\n",This
);
4748 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4749 list_remove(&tlbstr
->entry
);
4750 SysFreeString(tlbstr
->str
);
4754 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4755 list_remove(&tlbstr
->entry
);
4756 SysFreeString(tlbstr
->str
);
4760 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4761 list_remove(&tlbguid
->entry
);
4765 TLB_FreeCustData(&This
->custdata_list
);
4767 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4768 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4769 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4771 heap_free(This
->pTypeDesc
);
4773 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4775 if (pImpLib
->pImpTypeLib
)
4776 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4777 SysFreeString(pImpLib
->name
);
4779 list_remove(&pImpLib
->entry
);
4783 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, ref_type_next
, &This
->ref_list
, TLBRefType
, entry
)
4785 list_remove(&ref_type
->entry
);
4786 heap_free(ref_type
);
4789 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4790 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4791 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4793 heap_free(This
->typeinfos
);
4801 /* ITypeLib::GetTypeInfoCount
4803 * Returns the number of type descriptions in the type library
4805 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4807 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4808 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4809 return This
->TypeInfoCount
;
4812 /* ITypeLib::GetTypeInfo
4814 * retrieves the specified type description in the library.
4816 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4819 ITypeInfo
**ppTInfo
)
4821 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4823 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4826 return E_INVALIDARG
;
4828 if(index
>= This
->TypeInfoCount
)
4829 return TYPE_E_ELEMENTNOTFOUND
;
4831 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4832 ITypeInfo_AddRef(*ppTInfo
);
4838 /* ITypeLibs::GetTypeInfoType
4840 * Retrieves the type of a type description.
4842 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4847 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4849 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4852 return E_INVALIDARG
;
4854 if(index
>= This
->TypeInfoCount
)
4855 return TYPE_E_ELEMENTNOTFOUND
;
4857 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4862 /* ITypeLib::GetTypeInfoOfGuid
4864 * Retrieves the type description that corresponds to the specified GUID.
4867 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4870 ITypeInfo
**ppTInfo
)
4872 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4875 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4877 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4878 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4879 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4880 ITypeInfo_AddRef(*ppTInfo
);
4885 return TYPE_E_ELEMENTNOTFOUND
;
4888 /* ITypeLib::GetLibAttr
4890 * Retrieves the structure that contains the library's attributes.
4893 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4897 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4899 TRACE("(%p, %p)\n", This
, attr
);
4901 if (!attr
) return E_INVALIDARG
;
4903 *attr
= heap_alloc(sizeof(**attr
));
4904 if (!*attr
) return E_OUTOFMEMORY
;
4906 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4907 (*attr
)->lcid
= This
->set_lcid
;
4908 (*attr
)->syskind
= This
->syskind
;
4909 (*attr
)->wMajorVerNum
= This
->ver_major
;
4910 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4911 (*attr
)->wLibFlags
= This
->libflags
;
4916 /* ITypeLib::GetTypeComp
4918 * Enables a client compiler to bind to a library's types, variables,
4919 * constants, and global functions.
4922 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4924 ITypeComp
**ppTComp
)
4926 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4928 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4929 *ppTComp
= &This
->ITypeComp_iface
;
4930 ITypeComp_AddRef(*ppTComp
);
4935 /* ITypeLib::GetDocumentation
4937 * Retrieves the library's documentation string, the complete Help file name
4938 * and path, and the context identifier for the library Help topic in the Help
4941 * On a successful return all non-null BSTR pointers will have been set,
4944 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4948 BSTR
*pBstrDocString
,
4949 DWORD
*pdwHelpContext
,
4950 BSTR
*pBstrHelpFile
)
4952 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4953 HRESULT result
= E_INVALIDARG
;
4956 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4958 pBstrName
, pBstrDocString
,
4959 pdwHelpContext
, pBstrHelpFile
);
4963 /* documentation for the typelib */
4968 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4976 if (This
->DocString
)
4978 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4982 *pBstrDocString
= NULL
;
4986 *pdwHelpContext
= This
->dwHelpContext
;
4992 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
4996 *pBstrHelpFile
= NULL
;
5003 /* for a typeinfo */
5004 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5006 if(SUCCEEDED(result
))
5008 result
= ITypeInfo_GetDocumentation(pTInfo
,
5012 pdwHelpContext
, pBstrHelpFile
);
5014 ITypeInfo_Release(pTInfo
);
5019 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5021 if (pBstrName
) SysFreeString (*pBstrName
);
5023 return STG_E_INSUFFICIENTMEMORY
;
5028 * Indicates whether a passed-in string contains the name of a type or member
5029 * described in the library.
5032 static HRESULT WINAPI
ITypeLib2_fnIsName(
5038 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5040 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5042 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5046 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5047 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5048 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5049 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5050 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5052 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5053 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5054 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5055 goto ITypeLib2_fnIsName_exit
;
5058 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5059 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5060 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5066 ITypeLib2_fnIsName_exit
:
5067 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5068 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5073 /* ITypeLib::FindName
5075 * Finds occurrences of a type description in a type library. This may be used
5076 * to quickly verify that a name exists in a type library.
5079 static HRESULT WINAPI
ITypeLib2_fnFindName(
5083 ITypeInfo
**ppTInfo
,
5087 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5092 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5094 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5095 return E_INVALIDARG
;
5097 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5098 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5099 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5103 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5104 memid
[count
] = MEMBERID_NIL
;
5105 goto ITypeLib2_fnFindName_exit
;
5108 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5109 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5111 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5112 memid
[count
] = func
->funcdesc
.memid
;
5113 goto ITypeLib2_fnFindName_exit
;
5117 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->typeattr
.cVars
, name
);
5119 memid
[count
] = var
->vardesc
.memid
;
5120 goto ITypeLib2_fnFindName_exit
;
5124 ITypeLib2_fnFindName_exit
:
5125 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5126 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5129 TRACE("found %d typeinfos\n", count
);
5136 /* ITypeLib::ReleaseTLibAttr
5138 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5141 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5143 TLIBATTR
*pTLibAttr
)
5145 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5146 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5147 heap_free(pTLibAttr
);
5150 /* ITypeLib2::GetCustData
5152 * gets the custom data
5154 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5159 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5160 TLBCustData
*pCData
;
5162 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5164 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5166 return TYPE_E_ELEMENTNOTFOUND
;
5168 VariantInit(pVarVal
);
5169 VariantCopy(pVarVal
, &pCData
->data
);
5174 /* ITypeLib2::GetLibStatistics
5176 * Returns statistics about a type library that are required for efficient
5177 * sizing of hash tables.
5180 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5182 ULONG
*pcUniqueNames
,
5183 ULONG
*pcchUniqueNames
)
5185 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5187 FIXME("(%p): stub!\n", This
);
5189 if(pcUniqueNames
) *pcUniqueNames
=1;
5190 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5194 /* ITypeLib2::GetDocumentation2
5196 * Retrieves the library's documentation string, the complete Help file name
5197 * and path, the localization context to use, and the context ID for the
5198 * library Help topic in the Help file.
5201 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5205 BSTR
*pbstrHelpString
,
5206 DWORD
*pdwHelpStringContext
,
5207 BSTR
*pbstrHelpStringDll
)
5209 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5213 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5215 /* the help string should be obtained from the helpstringdll,
5216 * using the _DLLGetDocumentation function, based on the supplied
5217 * lcid. Nice to do sometime...
5221 /* documentation for the typelib */
5223 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5224 if(pdwHelpStringContext
)
5225 *pdwHelpStringContext
=This
->dwHelpContext
;
5226 if(pbstrHelpStringDll
)
5227 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5233 /* for a typeinfo */
5234 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5236 if(SUCCEEDED(result
))
5238 ITypeInfo2
* pTInfo2
;
5239 result
= ITypeInfo_QueryInterface(pTInfo
,
5241 (LPVOID
*) &pTInfo2
);
5243 if(SUCCEEDED(result
))
5245 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5249 pdwHelpStringContext
,
5250 pbstrHelpStringDll
);
5252 ITypeInfo2_Release(pTInfo2
);
5255 ITypeInfo_Release(pTInfo
);
5261 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5263 TLBCustData
*pCData
;
5267 ct
= list_count(custdata_list
);
5269 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5270 if(!pCustData
->prgCustData
)
5271 return E_OUTOFMEMORY
;
5273 pCustData
->cCustData
= ct
;
5275 cdi
= pCustData
->prgCustData
;
5276 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5277 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5278 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5286 /* ITypeLib2::GetAllCustData
5288 * Gets all custom data items for the library.
5291 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5293 CUSTDATA
*pCustData
)
5295 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5296 TRACE("(%p)->(%p)\n", This
, pCustData
);
5297 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5300 static const ITypeLib2Vtbl tlbvt
= {
5301 ITypeLib2_fnQueryInterface
,
5303 ITypeLib2_fnRelease
,
5304 ITypeLib2_fnGetTypeInfoCount
,
5305 ITypeLib2_fnGetTypeInfo
,
5306 ITypeLib2_fnGetTypeInfoType
,
5307 ITypeLib2_fnGetTypeInfoOfGuid
,
5308 ITypeLib2_fnGetLibAttr
,
5309 ITypeLib2_fnGetTypeComp
,
5310 ITypeLib2_fnGetDocumentation
,
5312 ITypeLib2_fnFindName
,
5313 ITypeLib2_fnReleaseTLibAttr
,
5315 ITypeLib2_fnGetCustData
,
5316 ITypeLib2_fnGetLibStatistics
,
5317 ITypeLib2_fnGetDocumentation2
,
5318 ITypeLib2_fnGetAllCustData
5322 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5324 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5326 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5329 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5331 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5333 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5336 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5338 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5340 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5343 static HRESULT WINAPI
ITypeLibComp_fnBind(
5348 ITypeInfo
** ppTInfo
,
5349 DESCKIND
* pDescKind
,
5352 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5353 BOOL typemismatch
= FALSE
;
5356 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5358 *pDescKind
= DESCKIND_NONE
;
5359 pBindPtr
->lptcomp
= NULL
;
5362 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5363 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5364 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5366 /* FIXME: check wFlags here? */
5367 /* FIXME: we should use a hash table to look this info up using lHash
5368 * instead of an O(n) search */
5369 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5370 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5372 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5374 *pDescKind
= DESCKIND_TYPECOMP
;
5375 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5376 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5377 TRACE("module or enum: %s\n", debugstr_w(szName
));
5382 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5383 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5385 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5388 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5389 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5391 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5394 else if (hr
== TYPE_E_TYPEMISMATCH
)
5395 typemismatch
= TRUE
;
5398 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5399 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5401 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5403 ITypeInfo
*subtypeinfo
;
5405 DESCKIND subdesckind
;
5407 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5408 &subtypeinfo
, &subdesckind
, &subbindptr
);
5409 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5411 TYPEDESC tdesc_appobject
;
5412 const VARDESC vardesc_appobject
=
5415 NULL
, /* lpstrSchema */
5430 VAR_STATIC
/* varkind */
5433 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5434 tdesc_appobject
.vt
= VT_USERDEFINED
;
5436 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5438 /* cleanup things filled in by Bind call so we can put our
5439 * application object data in there instead */
5440 switch (subdesckind
)
5442 case DESCKIND_FUNCDESC
:
5443 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5445 case DESCKIND_VARDESC
:
5446 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5451 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5453 if (pTypeInfo
->hreftype
== -1)
5454 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5456 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5460 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5461 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5462 ITypeInfo_AddRef(*ppTInfo
);
5465 else if (hr
== TYPE_E_TYPEMISMATCH
)
5466 typemismatch
= TRUE
;
5472 TRACE("type mismatch %s\n", debugstr_w(szName
));
5473 return TYPE_E_TYPEMISMATCH
;
5477 TRACE("name not found %s\n", debugstr_w(szName
));
5482 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5486 ITypeInfo
** ppTInfo
,
5487 ITypeComp
** ppTComp
)
5489 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5490 ITypeInfoImpl
*info
;
5492 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5494 if(!szName
|| !ppTInfo
|| !ppTComp
)
5495 return E_INVALIDARG
;
5497 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5504 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5505 ITypeInfo_AddRef(*ppTInfo
);
5506 *ppTComp
= &info
->ITypeComp_iface
;
5507 ITypeComp_AddRef(*ppTComp
);
5512 static const ITypeCompVtbl tlbtcvt
=
5515 ITypeLibComp_fnQueryInterface
,
5516 ITypeLibComp_fnAddRef
,
5517 ITypeLibComp_fnRelease
,
5519 ITypeLibComp_fnBind
,
5520 ITypeLibComp_fnBindType
5523 /*================== ITypeInfo(2) Methods ===================================*/
5524 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5526 ITypeInfoImpl
*pTypeInfoImpl
;
5528 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5531 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5532 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5533 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5534 pTypeInfoImpl
->ref
= 0;
5535 pTypeInfoImpl
->hreftype
= -1;
5536 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5537 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5538 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5539 list_init(pTypeInfoImpl
->pcustdata_list
);
5541 TRACE("(%p)\n", pTypeInfoImpl
);
5542 return pTypeInfoImpl
;
5545 /* ITypeInfo::QueryInterface
5547 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5552 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5554 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5557 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5558 IsEqualIID(riid
,&IID_ITypeInfo
)||
5559 IsEqualIID(riid
,&IID_ITypeInfo2
))
5560 *ppvObject
= &This
->ITypeInfo2_iface
;
5561 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5562 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5563 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5564 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5565 *ppvObject
= &This
->ITypeComp_iface
;
5568 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5569 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5572 TRACE("-- Interface: E_NOINTERFACE\n");
5573 return E_NOINTERFACE
;
5576 /* ITypeInfo::AddRef
5578 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5580 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5581 ULONG ref
= InterlockedIncrement(&This
->ref
);
5583 TRACE("(%p)->ref is %u\n",This
, ref
);
5585 if (ref
== 1 /* incremented from 0 */)
5586 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5591 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5595 TRACE("destroying ITypeInfo(%p)\n",This
);
5597 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5600 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5601 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5603 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5604 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5605 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5606 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5608 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5609 heap_free(pFInfo
->pParamDesc
);
5610 TLB_FreeCustData(&pFInfo
->custdata_list
);
5612 heap_free(This
->funcdescs
);
5614 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5616 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5617 if (pVInfo
->vardesc_create
) {
5618 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5619 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5620 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5621 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5623 TLB_FreeCustData(&pVInfo
->custdata_list
);
5625 heap_free(This
->vardescs
);
5627 if(This
->impltypes
){
5628 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5629 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5630 TLB_FreeCustData(&pImpl
->custdata_list
);
5632 heap_free(This
->impltypes
);
5635 TLB_FreeCustData(&This
->custdata_list
);
5640 /* ITypeInfo::Release
5642 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5644 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5645 ULONG ref
= InterlockedDecrement(&This
->ref
);
5647 TRACE("(%p)->(%u)\n",This
, ref
);
5651 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5652 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5653 if (not_attached_to_typelib
)
5655 /* otherwise This will be freed when typelib is freed */
5661 /* ITypeInfo::GetTypeAttr
5663 * Retrieves a TYPEATTR structure that contains the attributes of the type
5667 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5668 LPTYPEATTR
*ppTypeAttr
)
5670 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5673 TRACE("(%p)\n",This
);
5675 size
= sizeof(**ppTypeAttr
);
5676 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5677 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5679 *ppTypeAttr
= heap_alloc(size
);
5681 return E_OUTOFMEMORY
;
5683 **ppTypeAttr
= This
->typeattr
;
5684 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5686 if (This
->tdescAlias
)
5687 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5689 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5690 /* This should include all the inherited funcs */
5691 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5692 /* This is always the size of IDispatch's vtbl */
5693 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5694 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5699 /* ITypeInfo::GetTypeComp
5701 * Retrieves the ITypeComp interface for the type description, which enables a
5702 * client compiler to bind to the type description's members.
5705 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5706 ITypeComp
* *ppTComp
)
5708 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5710 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5712 *ppTComp
= &This
->ITypeComp_iface
;
5713 ITypeComp_AddRef(*ppTComp
);
5717 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5719 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5720 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5721 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5725 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5728 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5729 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5731 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5732 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5733 *buffer
+= sizeof(PARAMDESCEX
);
5734 *pparamdescex_dest
= *pparamdescex_src
;
5735 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5736 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5737 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5738 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5741 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5745 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5747 UINT len
= SysStringLen(str
), i
;
5748 for (i
= 0; i
< len
; ++i
)
5754 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5756 if (V_VT(var
) == VT_INT
)
5757 return VariantChangeType(var
, var
, 0, VT_I4
);
5758 else if (V_VT(var
) == VT_UINT
)
5759 return VariantChangeType(var
, var
, 0, VT_UI4
);
5760 else if (V_VT(var
) == VT_BSTR
)
5761 return TLB_SanitizeBSTR(V_BSTR(var
));
5766 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5768 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5769 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5772 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5776 SIZE_T size
= sizeof(*src
);
5780 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5781 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5782 for (i
= 0; i
< src
->cParams
; i
++)
5784 size
+= sizeof(ELEMDESC
);
5785 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5788 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5789 if (!dest
) return E_OUTOFMEMORY
;
5792 if (dispinterface
) /* overwrite funckind */
5793 dest
->funckind
= FUNC_DISPATCH
;
5794 buffer
= (char *)(dest
+ 1);
5796 dest
->oVft
= dest
->oVft
& 0xFFFC;
5798 if (dest
->cScodes
) {
5799 dest
->lprgscode
= (SCODE
*)buffer
;
5800 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5801 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5803 dest
->lprgscode
= NULL
;
5805 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5808 SysFreeString((BSTR
)dest
);
5812 if (dest
->cParams
) {
5813 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5814 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5815 for (i
= 0; i
< src
->cParams
; i
++)
5817 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5823 /* undo the above actions */
5824 for (i
= i
- 1; i
>= 0; i
--)
5825 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5826 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5827 SysFreeString((BSTR
)dest
);
5831 dest
->lprgelemdescParam
= NULL
;
5833 /* special treatment for dispinterfaces: this makes functions appear
5834 * to return their [retval] value when it is really returning an
5836 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5838 if (dest
->cParams
&&
5839 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5841 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5842 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5844 ERR("elemdesc should have started with VT_PTR instead of:\n");
5846 dump_ELEMDESC(elemdesc
);
5847 return E_UNEXPECTED
;
5850 /* copy last parameter to the return value. we are using a flat
5851 * buffer so there is no danger of leaking memory in
5853 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5855 /* remove the last parameter */
5859 /* otherwise this function is made to appear to have no return
5861 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5869 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5871 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5872 if (var_desc
->varkind
== VAR_CONST
)
5873 VariantClear(var_desc
->u
.lpvarValue
);
5874 SysFreeString((BSTR
)var_desc
);
5877 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5879 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5881 if (index
>= This
->typeattr
.cFuncs
)
5882 return TYPE_E_ELEMENTNOTFOUND
;
5884 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5888 /* internal function to make the inherited interfaces' methods appear
5889 * part of the interface */
5890 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5891 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5893 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5895 UINT implemented_funcs
= 0;
5900 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5904 ITypeInfo
*pSubTypeInfo
;
5907 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5911 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5914 &sub_funcs
, hrefoffset
);
5915 implemented_funcs
+= sub_funcs
;
5916 ITypeInfo_Release(pSubTypeInfo
);
5919 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5923 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5927 if (index
< implemented_funcs
)
5928 return E_INVALIDARG
;
5929 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5933 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5935 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5938 switch (pTypeDesc
->vt
)
5940 case VT_USERDEFINED
:
5941 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5945 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5948 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5956 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5959 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5960 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5961 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5964 /* ITypeInfo::GetFuncDesc
5966 * Retrieves the FUNCDESC structure that contains information about a
5967 * specified function.
5970 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5971 LPFUNCDESC
*ppFuncDesc
)
5973 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5974 const FUNCDESC
*internal_funcdesc
;
5976 UINT hrefoffset
= 0;
5978 TRACE("(%p) index %d\n", This
, index
);
5981 return E_INVALIDARG
;
5983 if (This
->needs_layout
)
5984 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5986 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5987 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5988 &internal_funcdesc
, NULL
,
5991 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5992 &internal_funcdesc
);
5995 WARN("description for function %d not found\n", index
);
5999 hr
= TLB_AllocAndInitFuncDesc(
6002 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6004 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
6005 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6007 TRACE("-- 0x%08x\n", hr
);
6011 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6015 SIZE_T size
= sizeof(*src
);
6018 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6019 if (src
->varkind
== VAR_CONST
)
6020 size
+= sizeof(VARIANT
);
6021 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6023 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6024 if (!dest
) return E_OUTOFMEMORY
;
6027 buffer
= (char *)(dest
+ 1);
6028 if (src
->lpstrSchema
)
6031 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6032 len
= strlenW(src
->lpstrSchema
);
6033 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6034 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6037 if (src
->varkind
== VAR_CONST
)
6041 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6042 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6043 buffer
+= sizeof(VARIANT
);
6044 VariantInit(dest
->u
.lpvarValue
);
6045 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6048 SysFreeString((BSTR
)dest
);
6052 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6055 if (src
->varkind
== VAR_CONST
)
6056 VariantClear(dest
->u
.lpvarValue
);
6057 SysFreeString((BSTR
)dest
);
6064 /* ITypeInfo::GetVarDesc
6066 * Retrieves a VARDESC structure that describes the specified variable.
6069 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6070 LPVARDESC
*ppVarDesc
)
6072 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6073 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6075 TRACE("(%p) index %d\n", This
, index
);
6077 if(index
>= This
->typeattr
.cVars
)
6078 return TYPE_E_ELEMENTNOTFOUND
;
6080 if (This
->needs_layout
)
6081 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6083 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6086 /* ITypeInfo_GetNames
6088 * Retrieves the variable with the specified member ID (or the name of the
6089 * property or method and its parameters) that correspond to the specified
6092 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6093 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6095 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6096 const TLBFuncDesc
*pFDesc
;
6097 const TLBVarDesc
*pVDesc
;
6099 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6102 return E_INVALIDARG
;
6106 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
6109 if(!cMaxNames
|| !pFDesc
->Name
)
6112 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6115 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6116 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6118 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6124 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
6127 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6132 if(This
->impltypes
&&
6133 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
6134 /* recursive search */
6137 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6138 if(SUCCEEDED(result
))
6140 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6141 ITypeInfo_Release(pTInfo
);
6144 WARN("Could not search inherited interface!\n");
6148 WARN("no names found\n");
6151 return TYPE_E_ELEMENTNOTFOUND
;
6157 /* ITypeInfo::GetRefTypeOfImplType
6159 * If a type description describes a COM class, it retrieves the type
6160 * description of the implemented interface types. For an interface,
6161 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6165 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6170 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6173 TRACE("(%p) index %d\n", This
, index
);
6174 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6178 /* only valid on dual interfaces;
6179 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6182 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6188 hr
= TYPE_E_ELEMENTNOTFOUND
;
6191 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6193 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6194 *pRefType
= This
->pTypeLib
->dispatch_href
;
6198 if(index
>= This
->typeattr
.cImplTypes
)
6199 hr
= TYPE_E_ELEMENTNOTFOUND
;
6201 *pRefType
= This
->impltypes
[index
].hRef
;
6202 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6210 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6212 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6218 /* ITypeInfo::GetImplTypeFlags
6220 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6221 * or base interface in a type description.
6223 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6224 UINT index
, INT
*pImplTypeFlags
)
6226 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6228 TRACE("(%p) index %d\n", This
, index
);
6231 return E_INVALIDARG
;
6233 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6234 *pImplTypeFlags
= 0;
6238 if(index
>= This
->typeattr
.cImplTypes
)
6239 return TYPE_E_ELEMENTNOTFOUND
;
6241 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6247 * Maps between member names and member IDs, and parameter names and
6250 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6251 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6253 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6254 const TLBVarDesc
*pVDesc
;
6258 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6261 /* init out parameters in case of failure */
6262 for (i
= 0; i
< cNames
; i
++)
6263 pMemId
[i
] = MEMBERID_NIL
;
6265 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6267 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6268 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6269 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6270 for(i
=1; i
< cNames
; i
++){
6271 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6272 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6274 if( j
<pFDesc
->funcdesc
.cParams
)
6277 ret
=DISP_E_UNKNOWNNAME
;
6279 TRACE("-- 0x%08x\n", ret
);
6283 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, *rgszNames
);
6286 *pMemId
= pVDesc
->vardesc
.memid
;
6289 /* not found, see if it can be found in an inherited interface */
6290 if(This
->impltypes
) {
6291 /* recursive search */
6293 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6295 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6296 ITypeInfo_Release(pTInfo
);
6299 WARN("Could not search inherited interface!\n");
6301 WARN("no names found\n");
6302 return DISP_E_UNKNOWNNAME
;
6308 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6309 __ASM_GLOBAL_FUNC( call_method
,
6311 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6312 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6313 "movl %esp,%ebp\n\t"
6314 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6316 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6318 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6319 "movl 12(%ebp),%edx\n\t"
6320 "movl %esp,%edi\n\t"
6323 "subl %edx,%edi\n\t"
6324 "andl $~15,%edi\n\t"
6325 "movl %edi,%esp\n\t"
6326 "movl 12(%ebp),%ecx\n\t"
6327 "movl 16(%ebp),%esi\n\t"
6330 "1:\tcall *8(%ebp)\n\t"
6331 "subl %esp,%edi\n\t"
6332 "movl 20(%ebp),%ecx\n\t"
6333 "movl %edi,(%ecx)\n\t"
6334 "leal -8(%ebp),%esp\n\t"
6336 __ASM_CFI(".cfi_same_value %edi\n\t")
6338 __ASM_CFI(".cfi_same_value %esi\n\t")
6340 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6341 __ASM_CFI(".cfi_same_value %ebp\n\t")
6344 /* same function but returning floating point */
6345 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6347 /* ITypeInfo::Invoke
6349 * Invokes a method, or accesses a property of an object, that implements the
6350 * interface described by the type description.
6353 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6357 if (TRACE_ON(ole
)) {
6359 TRACE("Calling %p(",func
);
6360 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6361 if (nrargs
> 30) TRACE("...");
6368 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6371 FIXME("unsupported calling convention %d\n",callconv
);
6375 TRACE("returns %08x\n",res
);
6379 #elif defined(__x86_64__)
6381 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6382 __ASM_GLOBAL_FUNC( call_method
,
6384 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6385 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6386 "movq %rsp,%rbp\n\t"
6387 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6389 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6391 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6392 "movq %rcx,%rax\n\t"
6395 "cmovgq %rdx,%rcx\n\t"
6396 "leaq 0(,%rcx,8),%rdx\n\t"
6397 "subq %rdx,%rsp\n\t"
6398 "andq $~15,%rsp\n\t"
6399 "movq %rsp,%rdi\n\t"
6402 "movq 0(%rsp),%rcx\n\t"
6403 "movq 8(%rsp),%rdx\n\t"
6404 "movq 16(%rsp),%r8\n\t"
6405 "movq 24(%rsp),%r9\n\t"
6406 "movq 0(%rsp),%xmm0\n\t"
6407 "movq 8(%rsp),%xmm1\n\t"
6408 "movq 16(%rsp),%xmm2\n\t"
6409 "movq 24(%rsp),%xmm3\n\t"
6411 "leaq -16(%rbp),%rsp\n\t"
6413 __ASM_CFI(".cfi_same_value %rdi\n\t")
6415 __ASM_CFI(".cfi_same_value %rsi\n\t")
6416 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6418 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6419 __ASM_CFI(".cfi_same_value %rbp\n\t")
6422 /* same function but returning floating point */
6423 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6425 #endif /* __x86_64__ */
6427 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6430 ITypeInfo
*tinfo2
= NULL
;
6431 TYPEATTR
*tattr
= NULL
;
6433 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6436 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6438 tdesc
->u
.hreftype
, hr
);
6441 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6444 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6445 ITypeInfo_Release(tinfo2
);
6449 switch (tattr
->typekind
)
6456 tdesc
= &tattr
->tdescAlias
;
6457 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6460 case TKIND_INTERFACE
:
6461 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6467 case TKIND_DISPATCH
:
6476 FIXME("TKIND_RECORD unhandled.\n");
6481 FIXME("TKIND_UNION unhandled.\n");
6486 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6490 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6491 ITypeInfo_Release(tinfo2
);
6495 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6499 /* enforce only one level of pointer indirection */
6500 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6502 tdesc
= tdesc
->u
.lptdesc
;
6504 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6505 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6506 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6507 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6508 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6510 VARTYPE vt_userdefined
= 0;
6511 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6512 if (tdesc
->vt
== VT_PTR
)
6514 vt_userdefined
= VT_BYREF
;
6515 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6517 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6519 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6520 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6522 *vt
|= vt_userdefined
;
6534 case VT_USERDEFINED
:
6535 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6542 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6543 hr
= DISP_E_BADVARTYPE
;
6547 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6562 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6568 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6572 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6574 ITypeInfo_Release(tinfo2
);
6578 switch(tattr
->typekind
) {
6580 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6583 case TKIND_INTERFACE
:
6584 case TKIND_DISPATCH
:
6585 *guid
= tattr
->guid
;
6589 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6590 hres
= E_UNEXPECTED
;
6593 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6594 ITypeInfo_Release(tinfo2
);
6598 /***********************************************************************
6599 * DispCallFunc (OLEAUT32.@)
6601 * Invokes a function of the specified calling convention, passing the
6602 * specified arguments and returns the result.
6605 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6606 * oVft [I] The offset in the vtable. See notes.
6607 * cc [I] Calling convention of the function to call.
6608 * vtReturn [I] The return type of the function.
6609 * cActuals [I] Number of parameters.
6610 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6611 * prgpvarg [I] The arguments to pass.
6612 * pvargResult [O] The return value of the function. Can be NULL.
6616 * Failure: HRESULT code.
6619 * The HRESULT return value of this function is not affected by the return
6620 * value of the user supplied function, which is returned in pvargResult.
6622 * If pvInstance is NULL then a non-object function is to be called and oVft
6623 * is the address of the function to call.
6625 * The cc parameter can be one of the following values:
6638 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6639 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6642 int argspos
, stack_offset
;
6647 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6648 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6649 pvargResult
, V_VT(pvargResult
));
6651 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6653 FIXME("unsupported calling convention %d\n",cc
);
6654 return E_INVALIDARG
;
6657 /* maximum size for an argument is sizeof(VARIANT) */
6658 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6660 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6664 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6665 func
= vtable
[oVft
/sizeof(void *)];
6666 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6668 else func
= (void *)oVft
;
6670 for (i
= 0; i
< cActuals
; i
++)
6672 VARIANT
*arg
= prgpvarg
[i
];
6683 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6684 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6688 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6689 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6691 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6692 args
[argspos
++] = V_BOOL(arg
);
6695 args
[argspos
++] = V_UI4(arg
);
6698 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6704 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6707 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6711 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6715 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6716 call_method( func
, argspos
, args
, &stack_offset
);
6721 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6724 WARN("invalid return type %u\n", vtReturn
);
6726 return E_INVALIDARG
;
6728 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6732 if (stack_offset
&& cc
== CC_STDCALL
)
6734 WARN( "stack pointer off by %d\n", stack_offset
);
6735 return DISP_E_BADCALLEE
;
6737 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6738 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6741 #elif defined(__x86_64__)
6747 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6748 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6749 pvargResult
, V_VT(pvargResult
));
6751 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6753 FIXME("unsupported calling convention %d\n",cc
);
6754 return E_INVALIDARG
;
6757 /* maximum size for an argument is sizeof(DWORD_PTR) */
6758 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6760 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6764 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6765 func
= vtable
[oVft
/sizeof(void *)];
6766 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6768 else func
= (void *)oVft
;
6770 for (i
= 0; i
< cActuals
; i
++)
6772 VARIANT
*arg
= prgpvarg
[i
];
6778 args
[argspos
++] = (ULONG_PTR
)arg
;
6780 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6781 args
[argspos
++] = V_BOOL(arg
);
6784 args
[argspos
++] = V_UI8(arg
);
6787 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6793 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6797 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6801 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6802 call_method( func
, argspos
, args
);
6805 WARN("invalid return type %u\n", vtReturn
);
6807 return E_INVALIDARG
;
6809 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6813 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6814 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6818 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6819 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6824 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6826 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6829 #define INVBUF_ELEMENT_SIZE \
6830 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6831 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6832 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6833 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6834 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6835 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6836 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6837 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6839 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6844 DISPPARAMS
*pDispParams
,
6845 VARIANT
*pVarResult
,
6846 EXCEPINFO
*pExcepInfo
,
6849 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6851 unsigned int var_index
;
6854 const TLBFuncDesc
*pFuncInfo
;
6857 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6858 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6861 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6862 return DISP_E_MEMBERNOTFOUND
;
6866 ERR("NULL pDispParams not allowed\n");
6867 return E_INVALIDARG
;
6870 dump_DispParms(pDispParams
);
6872 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6874 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6875 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6876 return E_INVALIDARG
;
6879 /* we do this instead of using GetFuncDesc since it will return a fake
6880 * FUNCDESC for dispinterfaces and we want the real function description */
6881 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
6882 pFuncInfo
= &This
->funcdescs
[fdc
];
6883 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6884 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6885 !func_restricted( &pFuncInfo
->funcdesc
))
6889 if (fdc
< This
->typeattr
.cFuncs
) {
6890 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6894 TRACE("invoking:\n");
6895 dump_TLBFuncDescOne(pFuncInfo
);
6898 switch (func_desc
->funckind
) {
6899 case FUNC_PUREVIRTUAL
:
6900 case FUNC_VIRTUAL
: {
6901 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6903 VARIANT retval
; /* pointer for storing byref retvals in */
6904 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6905 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6906 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6907 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6908 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6909 UINT vargs_converted
=0;
6913 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6915 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6917 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6918 hres
= DISP_E_PARAMNOTFOUND
;
6923 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6925 ERR("functions with the vararg attribute do not support named arguments\n");
6926 hres
= DISP_E_NONAMEDARGS
;
6930 for (i
= 0; i
< func_desc
->cParams
; i
++)
6932 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6933 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6938 TRACE("changing args\n");
6939 for (i
= 0; i
< func_desc
->cParams
; i
++)
6941 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6942 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6943 VARIANTARG
*src_arg
;
6945 if (wParamFlags
& PARAMFLAG_FLCID
)
6948 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6950 V_I4(arg
) = This
->pTypeLib
->lcid
;
6959 for (j
= 0; j
< cNamedArgs
; j
++)
6960 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6962 src_arg
= &pDispParams
->rgvarg
[j
];
6967 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6969 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6973 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6975 /* under most conditions the caller is not allowed to
6976 * pass in a dispparam arg in the index of what would be
6977 * the retval parameter. however, there is an exception
6978 * where the extra parameter is used in an extra
6979 * IDispatch::Invoke below */
6980 if ((i
< pDispParams
->cArgs
) &&
6981 ((func_desc
->cParams
!= 1) || !pVarResult
||
6982 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
6984 hres
= DISP_E_BADPARAMCOUNT
;
6988 /* note: this check is placed so that if the caller passes
6989 * in a VARIANTARG for the retval we just ignore it, like
6991 if (i
== func_desc
->cParams
- 1)
6994 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6995 memset(arg
, 0, sizeof(*arg
));
6996 V_VT(arg
) = rgvt
[i
];
6997 memset(&retval
, 0, sizeof(retval
));
6998 V_BYREF(arg
) = &retval
;
7002 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7003 hres
= E_UNEXPECTED
;
7009 TRACE("%s\n", debugstr_variant(src_arg
));
7011 if(rgvt
[i
]!=V_VT(src_arg
))
7013 if (rgvt
[i
] == VT_VARIANT
)
7014 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7015 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7017 if (rgvt
[i
] == V_VT(src_arg
))
7018 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7021 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7022 if (wParamFlags
& PARAMFLAG_FIN
)
7023 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7024 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7026 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7028 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7031 SAFEARRAYBOUND bound
;
7035 bound
.cElements
= pDispParams
->cArgs
-i
;
7036 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7038 ERR("SafeArrayCreate failed\n");
7041 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7044 ERR("SafeArrayAccessData failed with %x\n", hres
);
7045 SafeArrayDestroy(a
);
7048 for (j
= 0; j
< bound
.cElements
; j
++)
7049 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7050 hres
= SafeArrayUnaccessData(a
);
7053 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7054 SafeArrayDestroy(a
);
7057 if (rgvt
[i
] & VT_BYREF
)
7058 V_BYREF(&rgvarg
[i
]) = &a
;
7060 V_ARRAY(&rgvarg
[i
]) = a
;
7061 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7063 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7065 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7066 if (wParamFlags
& PARAMFLAG_FIN
)
7067 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7069 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7070 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7071 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7073 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7075 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7076 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7080 /* FIXME: this doesn't work for VT_BYREF arguments if
7081 * they are not the same type as in the paramdesc */
7082 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7083 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7084 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7089 ERR("failed to convert param %d to %s from %s\n", i
,
7090 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7093 prgpvarg
[i
] = &rgvarg
[i
];
7097 prgpvarg
[i
] = src_arg
;
7100 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7101 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7102 && V_UNKNOWN(prgpvarg
[i
])) {
7103 IUnknown
*userdefined_iface
;
7106 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7110 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7112 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7116 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7117 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7120 else if (wParamFlags
& PARAMFLAG_FOPT
)
7123 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7124 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7126 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7132 VARIANTARG
*missing_arg
;
7133 /* if the function wants a pointer to a variant then
7134 * set that up, otherwise just pass the VT_ERROR in
7135 * the argument by value */
7136 if (rgvt
[i
] & VT_BYREF
)
7138 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7139 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7140 V_VARIANTREF(arg
) = missing_arg
;
7144 V_VT(missing_arg
) = VT_ERROR
;
7145 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7150 hres
= DISP_E_BADPARAMCOUNT
;
7154 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7156 /* VT_VOID is a special case for return types, so it is not
7157 * handled in the general function */
7158 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7159 V_VT(&varresult
) = VT_EMPTY
;
7162 V_VT(&varresult
) = 0;
7163 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7164 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7167 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7168 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7169 prgpvarg
, &varresult
);
7171 vargs_converted
= 0;
7173 for (i
= 0; i
< func_desc
->cParams
; i
++)
7175 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7176 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7178 if (wParamFlags
& PARAMFLAG_FLCID
)
7180 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7182 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7186 VariantInit(pVarResult
);
7187 /* deref return value */
7188 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7191 VARIANT_ClearInd(prgpvarg
[i
]);
7193 else if (vargs_converted
< pDispParams
->cArgs
)
7195 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7196 if (wParamFlags
& PARAMFLAG_FOUT
)
7198 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7200 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7204 ERR("failed to convert param %d to vt %d\n", i
,
7205 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7210 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7211 func_desc
->cParamsOpt
< 0 &&
7212 i
== func_desc
->cParams
-1)
7214 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7217 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7220 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7223 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7226 ERR("SafeArrayAccessData failed with %x\n", hres
);
7229 for (j
= 0; j
<= ubound
; j
++)
7230 VariantClear(&v
[j
]);
7231 hres
= SafeArrayUnaccessData(a
);
7234 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7238 VariantClear(&rgvarg
[i
]);
7241 else if (wParamFlags
& PARAMFLAG_FOPT
)
7243 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7244 VariantClear(&rgvarg
[i
]);
7247 VariantClear(&missing_arg
[i
]);
7250 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7252 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7253 hres
= DISP_E_EXCEPTION
;
7256 IErrorInfo
*pErrorInfo
;
7257 pExcepInfo
->scode
= V_ERROR(&varresult
);
7258 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7260 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7261 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7262 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7263 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7265 IErrorInfo_Release(pErrorInfo
);
7269 if (V_VT(&varresult
) != VT_ERROR
)
7271 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7275 VariantClear(pVarResult
);
7276 *pVarResult
= varresult
;
7279 VariantClear(&varresult
);
7282 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7283 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7284 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7285 (pDispParams
->cArgs
!= 0))
7287 if (V_VT(pVarResult
) == VT_DISPATCH
)
7289 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7290 /* Note: not VariantClear; we still need the dispatch
7291 * pointer to be valid */
7292 VariantInit(pVarResult
);
7293 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7294 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7295 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7296 IDispatch_Release(pDispatch
);
7300 VariantClear(pVarResult
);
7301 hres
= DISP_E_NOTACOLLECTION
;
7309 case FUNC_DISPATCH
: {
7312 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7313 if (SUCCEEDED(hres
)) {
7314 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7315 hres
= IDispatch_Invoke(
7316 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7317 pVarResult
,pExcepInfo
,pArgErr
7320 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7321 IDispatch_Release(disp
);
7323 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7327 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7332 TRACE("-- 0x%08x\n", hres
);
7335 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7338 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7339 if(FAILED(hres
)) return hres
;
7341 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7342 dump_VARDESC(var_desc
);
7343 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7347 /* not found, look for it in inherited interfaces */
7348 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7349 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7350 if(This
->impltypes
) {
7351 /* recursive search */
7353 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7354 if(SUCCEEDED(hres
)){
7355 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7356 ITypeInfo_Release(pTInfo
);
7359 WARN("Could not search inherited interface!\n");
7362 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7363 return DISP_E_MEMBERNOTFOUND
;
7366 /* ITypeInfo::GetDocumentation
7368 * Retrieves the documentation string, the complete Help file name and path,
7369 * and the context ID for the Help topic for a specified type description.
7371 * (Can be tested by the Visual Basic Editor in Word for instance.)
7373 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7374 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7375 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7377 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7378 const TLBFuncDesc
*pFDesc
;
7379 const TLBVarDesc
*pVDesc
;
7380 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7381 " HelpContext(%p) HelpFile(%p)\n",
7382 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7383 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7385 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7387 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7389 *pdwHelpContext
=This
->dwHelpContext
;
7391 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7393 }else {/* for a member */
7394 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7397 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7399 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7401 *pdwHelpContext
=pFDesc
->helpcontext
;
7403 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7406 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
7409 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7411 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7413 *pdwHelpContext
=pVDesc
->HelpContext
;
7415 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7420 if(This
->impltypes
&&
7421 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7422 /* recursive search */
7425 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7426 if(SUCCEEDED(result
)) {
7427 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7428 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7429 ITypeInfo_Release(pTInfo
);
7432 WARN("Could not search inherited interface!\n");
7435 WARN("member %d not found\n", memid
);
7436 return TYPE_E_ELEMENTNOTFOUND
;
7439 /* ITypeInfo::GetDllEntry
7441 * Retrieves a description or specification of an entry point for a function
7444 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7445 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7448 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7449 const TLBFuncDesc
*pFDesc
;
7451 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7453 if (pBstrDllName
) *pBstrDllName
= NULL
;
7454 if (pBstrName
) *pBstrName
= NULL
;
7455 if (pwOrdinal
) *pwOrdinal
= 0;
7457 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7458 return TYPE_E_BADMODULEKIND
;
7460 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7462 dump_TypeInfo(This
);
7464 dump_TLBFuncDescOne(pFDesc
);
7467 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7469 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7471 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7479 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7482 return TYPE_E_ELEMENTNOTFOUND
;
7485 /* internal function to make the inherited interfaces' methods appear
7486 * part of the interface */
7487 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7488 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7490 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7493 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7495 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7497 ITypeInfo
*pSubTypeInfo
;
7499 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7503 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7505 ITypeInfo_Release(pSubTypeInfo
);
7509 *hRefType
-= DISPATCH_HREF_OFFSET
;
7511 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7512 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7517 struct search_res_tlb_params
7523 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7525 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7526 static const WCHAR formatW
[] = {'\\','%','d',0};
7527 WCHAR szPath
[MAX_PATH
+1];
7528 ITypeLib
*pTLib
= NULL
;
7532 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7535 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7538 if (snprintfW(szPath
+ len
, sizeof(szPath
)/sizeof(WCHAR
) - len
, formatW
, LOWORD(lpszName
)) < 0)
7541 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7544 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7545 if (IsEqualGUID(params
->guid
, impl
->guid
))
7547 params
->pTLib
= pTLib
;
7548 return FALSE
; /* stop enumeration */
7550 ITypeLib_Release(pTLib
);
7556 /* ITypeInfo::GetRefTypeInfo
7558 * If a type description references other type descriptions, it retrieves
7559 * the referenced type descriptions.
7561 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7564 ITypeInfo
**ppTInfo
)
7566 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7567 HRESULT result
= E_FAIL
;
7570 return E_INVALIDARG
;
7572 if ((INT
)hRefType
< 0) {
7573 ITypeInfoImpl
*pTypeInfoImpl
;
7575 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7576 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7577 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7578 return TYPE_E_ELEMENTNOTFOUND
;
7580 /* when we meet a DUAL typeinfo, we must create the alternate
7583 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7585 *pTypeInfoImpl
= *This
;
7586 pTypeInfoImpl
->ref
= 0;
7587 list_init(&pTypeInfoImpl
->custdata_list
);
7589 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7590 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7592 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7594 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7595 /* the AddRef implicitly adds a reference to the parent typelib, which
7596 * stops the copied data from being destroyed until the new typeinfo's
7597 * refcount goes to zero, but we need to signal to the new instance to
7598 * not free its data structures when it is destroyed */
7599 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7601 ITypeInfo_AddRef(*ppTInfo
);
7604 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7605 (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7607 HREFTYPE href_dispatch
= hRefType
;
7608 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7610 TLBRefType
*ref_type
;
7611 ITypeLib
*pTLib
= NULL
;
7614 if(!(hRefType
& 0x1)){
7615 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7617 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7620 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7621 ITypeInfo_AddRef(*ppTInfo
);
7627 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7629 if(ref_type
->reference
== (hRefType
& (~0x3)))
7632 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7634 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7638 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7640 TRACE("internal reference\n");
7641 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7643 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7644 TRACE("typeinfo in imported typelib that is already loaded\n");
7645 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7646 ITypeLib_AddRef(pTLib
);
7649 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
7650 struct search_res_tlb_params params
;
7653 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7655 /* Search in resource table */
7656 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
7657 params
.pTLib
= NULL
;
7658 EnumResourceNamesW(NULL
, TYPELIBW
, search_res_tlb
, (LONG_PTR
)¶ms
);
7659 pTLib
= params
.pTLib
;
7664 /* Search on disk */
7665 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7666 ref_type
->pImpTLInfo
->wVersionMajor
,
7667 ref_type
->pImpTLInfo
->wVersionMinor
,
7668 This
->pTypeLib
->syskind
,
7669 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7671 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7673 result
= LoadTypeLib(libnam
, &pTLib
);
7674 SysFreeString(libnam
);
7677 if(SUCCEEDED(result
)) {
7678 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7679 ITypeLib_AddRef(pTLib
);
7683 if(SUCCEEDED(result
)) {
7684 if(ref_type
->index
== TLB_REF_USE_GUID
)
7685 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7687 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7690 ITypeLib_Release(pTLib
);
7694 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7695 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7699 /* ITypeInfo::AddressOfMember
7701 * Retrieves the addresses of static functions or variables, such as those
7704 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7705 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7707 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7713 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7715 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7719 module
= LoadLibraryW(dll
);
7722 ERR("couldn't load %s\n", debugstr_w(dll
));
7724 SysFreeString(entry
);
7725 return STG_E_FILENOTFOUND
;
7727 /* FIXME: store library somewhere where we can free it */
7732 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7733 entryA
= heap_alloc(len
);
7734 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7736 *ppv
= GetProcAddress(module
, entryA
);
7738 ERR("function not found %s\n", debugstr_a(entryA
));
7744 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7746 ERR("function not found %d\n", ordinal
);
7750 SysFreeString(entry
);
7753 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7758 /* ITypeInfo::CreateInstance
7760 * Creates a new instance of a type that describes a component object class
7763 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7764 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7766 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7770 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7776 WARN("Not able to aggregate\n");
7777 return CLASS_E_NOAGGREGATION
;
7780 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7781 if(FAILED(hr
)) return hr
;
7783 if(pTA
->typekind
!= TKIND_COCLASS
)
7785 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7791 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7794 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7795 TRACE("GetActiveObject rets %08x\n", hr
);
7798 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7799 IUnknown_Release(pUnk
);
7804 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7805 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7809 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7813 /* ITypeInfo::GetMops
7815 * Retrieves marshalling information.
7817 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7820 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7821 FIXME("(%p %d) stub!\n", This
, memid
);
7826 /* ITypeInfo::GetContainingTypeLib
7828 * Retrieves the containing type library and the index of the type description
7829 * within that type library.
7831 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7832 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7834 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7836 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7838 *pIndex
=This
->index
;
7839 TRACE("returning pIndex=%d\n", *pIndex
);
7843 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
7844 ITypeLib_AddRef(*ppTLib
);
7845 TRACE("returning ppTLib=%p\n", *ppTLib
);
7851 /* ITypeInfo::ReleaseTypeAttr
7853 * Releases a TYPEATTR previously returned by Get
7856 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7857 TYPEATTR
* pTypeAttr
)
7859 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7860 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7861 heap_free(pTypeAttr
);
7864 /* ITypeInfo::ReleaseFuncDesc
7866 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7868 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7870 FUNCDESC
*pFuncDesc
)
7872 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7875 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7877 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7878 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7879 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7881 SysFreeString((BSTR
)pFuncDesc
);
7884 /* ITypeInfo::ReleaseVarDesc
7886 * Releases a VARDESC previously returned by GetVarDesc.
7888 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7891 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7892 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7894 TLB_FreeVarDesc(pVarDesc
);
7897 /* ITypeInfo2::GetTypeKind
7899 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7902 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7903 TYPEKIND
*pTypeKind
)
7905 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7906 *pTypeKind
= This
->typeattr
.typekind
;
7907 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7911 /* ITypeInfo2::GetTypeFlags
7913 * Returns the type flags without any allocations. This returns a DWORD type
7914 * flag, which expands the type flags without growing the TYPEATTR (type
7918 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7920 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7921 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
7922 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7926 /* ITypeInfo2::GetFuncIndexOfMemId
7927 * Binds to a specific member based on a known DISPID, where the member name
7928 * is not known (for example, when binding to a default member).
7931 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7932 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7934 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7938 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7939 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7940 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7943 if(fdc
< This
->typeattr
.cFuncs
) {
7947 result
= TYPE_E_ELEMENTNOTFOUND
;
7949 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7950 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7954 /* TypeInfo2::GetVarIndexOfMemId
7956 * Binds to a specific member based on a known DISPID, where the member name
7957 * is not known (for example, when binding to a default member).
7960 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7961 MEMBERID memid
, UINT
*pVarIndex
)
7963 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7964 TLBVarDesc
*pVarInfo
;
7966 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7968 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
7970 return TYPE_E_ELEMENTNOTFOUND
;
7972 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7977 /* ITypeInfo2::GetCustData
7979 * Gets the custom data
7981 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7986 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7987 TLBCustData
*pCData
;
7989 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7991 if(!guid
|| !pVarVal
)
7992 return E_INVALIDARG
;
7994 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
7996 VariantInit( pVarVal
);
7998 VariantCopy( pVarVal
, &pCData
->data
);
8000 VariantClear( pVarVal
);
8004 /* ITypeInfo2::GetFuncCustData
8006 * Gets the custom data
8008 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8014 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8015 TLBCustData
*pCData
;
8016 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8018 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8020 if(index
>= This
->typeattr
.cFuncs
)
8021 return TYPE_E_ELEMENTNOTFOUND
;
8023 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8025 return TYPE_E_ELEMENTNOTFOUND
;
8027 VariantInit(pVarVal
);
8028 VariantCopy(pVarVal
, &pCData
->data
);
8033 /* ITypeInfo2::GetParamCustData
8035 * Gets the custom data
8037 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8044 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8045 TLBCustData
*pCData
;
8046 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8048 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8049 debugstr_guid(guid
), pVarVal
);
8051 if(indexFunc
>= This
->typeattr
.cFuncs
)
8052 return TYPE_E_ELEMENTNOTFOUND
;
8054 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8055 return TYPE_E_ELEMENTNOTFOUND
;
8057 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8059 return TYPE_E_ELEMENTNOTFOUND
;
8061 VariantInit(pVarVal
);
8062 VariantCopy(pVarVal
, &pCData
->data
);
8067 /* ITypeInfo2::GetVarCustData
8069 * Gets the custom data
8071 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8077 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8078 TLBCustData
*pCData
;
8079 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8081 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8083 if(index
>= This
->typeattr
.cVars
)
8084 return TYPE_E_ELEMENTNOTFOUND
;
8086 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8088 return TYPE_E_ELEMENTNOTFOUND
;
8090 VariantInit(pVarVal
);
8091 VariantCopy(pVarVal
, &pCData
->data
);
8096 /* ITypeInfo2::GetImplCustData
8098 * Gets the custom data
8100 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8106 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8107 TLBCustData
*pCData
;
8108 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8110 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8112 if(index
>= This
->typeattr
.cImplTypes
)
8113 return TYPE_E_ELEMENTNOTFOUND
;
8115 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8117 return TYPE_E_ELEMENTNOTFOUND
;
8119 VariantInit(pVarVal
);
8120 VariantCopy(pVarVal
, &pCData
->data
);
8125 /* ITypeInfo2::GetDocumentation2
8127 * Retrieves the documentation string, the complete Help file name and path,
8128 * the localization context to use, and the context ID for the library Help
8129 * topic in the Help file.
8132 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8136 BSTR
*pbstrHelpString
,
8137 DWORD
*pdwHelpStringContext
,
8138 BSTR
*pbstrHelpStringDll
)
8140 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8141 const TLBFuncDesc
*pFDesc
;
8142 const TLBVarDesc
*pVDesc
;
8143 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8144 "HelpStringContext(%p) HelpStringDll(%p)\n",
8145 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8146 pbstrHelpStringDll
);
8147 /* the help string should be obtained from the helpstringdll,
8148 * using the _DLLGetDocumentation function, based on the supplied
8149 * lcid. Nice to do sometime...
8151 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8153 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8154 if(pdwHelpStringContext
)
8155 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8156 if(pbstrHelpStringDll
)
8157 *pbstrHelpStringDll
=
8158 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8160 }else {/* for a member */
8161 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
8164 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8165 if(pdwHelpStringContext
)
8166 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8167 if(pbstrHelpStringDll
)
8168 *pbstrHelpStringDll
=
8169 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8172 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
8175 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8176 if(pdwHelpStringContext
)
8177 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8178 if(pbstrHelpStringDll
)
8179 *pbstrHelpStringDll
=
8180 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8184 return TYPE_E_ELEMENTNOTFOUND
;
8187 /* ITypeInfo2::GetAllCustData
8189 * Gets all custom data items for the Type info.
8192 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8194 CUSTDATA
*pCustData
)
8196 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8198 TRACE("%p %p\n", This
, pCustData
);
8200 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8203 /* ITypeInfo2::GetAllFuncCustData
8205 * Gets all custom data items for the specified Function
8208 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8211 CUSTDATA
*pCustData
)
8213 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8214 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8216 TRACE("%p %u %p\n", This
, index
, pCustData
);
8218 if(index
>= This
->typeattr
.cFuncs
)
8219 return TYPE_E_ELEMENTNOTFOUND
;
8221 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8224 /* ITypeInfo2::GetAllParamCustData
8226 * Gets all custom data items for the Functions
8229 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8230 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8232 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8233 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8235 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8237 if(indexFunc
>= This
->typeattr
.cFuncs
)
8238 return TYPE_E_ELEMENTNOTFOUND
;
8240 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8241 return TYPE_E_ELEMENTNOTFOUND
;
8243 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8246 /* ITypeInfo2::GetAllVarCustData
8248 * Gets all custom data items for the specified Variable
8251 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8252 UINT index
, CUSTDATA
*pCustData
)
8254 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8255 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8257 TRACE("%p %u %p\n", This
, index
, pCustData
);
8259 if(index
>= This
->typeattr
.cVars
)
8260 return TYPE_E_ELEMENTNOTFOUND
;
8262 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8265 /* ITypeInfo2::GetAllImplCustData
8267 * Gets all custom data items for the specified implementation type
8270 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8273 CUSTDATA
*pCustData
)
8275 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8276 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8278 TRACE("%p %u %p\n", This
, index
, pCustData
);
8280 if(index
>= This
->typeattr
.cImplTypes
)
8281 return TYPE_E_ELEMENTNOTFOUND
;
8283 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8286 static const ITypeInfo2Vtbl tinfvt
=
8289 ITypeInfo_fnQueryInterface
,
8291 ITypeInfo_fnRelease
,
8293 ITypeInfo_fnGetTypeAttr
,
8294 ITypeInfo_fnGetTypeComp
,
8295 ITypeInfo_fnGetFuncDesc
,
8296 ITypeInfo_fnGetVarDesc
,
8297 ITypeInfo_fnGetNames
,
8298 ITypeInfo_fnGetRefTypeOfImplType
,
8299 ITypeInfo_fnGetImplTypeFlags
,
8300 ITypeInfo_fnGetIDsOfNames
,
8302 ITypeInfo_fnGetDocumentation
,
8303 ITypeInfo_fnGetDllEntry
,
8304 ITypeInfo_fnGetRefTypeInfo
,
8305 ITypeInfo_fnAddressOfMember
,
8306 ITypeInfo_fnCreateInstance
,
8307 ITypeInfo_fnGetMops
,
8308 ITypeInfo_fnGetContainingTypeLib
,
8309 ITypeInfo_fnReleaseTypeAttr
,
8310 ITypeInfo_fnReleaseFuncDesc
,
8311 ITypeInfo_fnReleaseVarDesc
,
8313 ITypeInfo2_fnGetTypeKind
,
8314 ITypeInfo2_fnGetTypeFlags
,
8315 ITypeInfo2_fnGetFuncIndexOfMemId
,
8316 ITypeInfo2_fnGetVarIndexOfMemId
,
8317 ITypeInfo2_fnGetCustData
,
8318 ITypeInfo2_fnGetFuncCustData
,
8319 ITypeInfo2_fnGetParamCustData
,
8320 ITypeInfo2_fnGetVarCustData
,
8321 ITypeInfo2_fnGetImplTypeCustData
,
8322 ITypeInfo2_fnGetDocumentation2
,
8323 ITypeInfo2_fnGetAllCustData
,
8324 ITypeInfo2_fnGetAllFuncCustData
,
8325 ITypeInfo2_fnGetAllParamCustData
,
8326 ITypeInfo2_fnGetAllVarCustData
,
8327 ITypeInfo2_fnGetAllImplTypeCustData
,
8330 /******************************************************************************
8331 * CreateDispTypeInfo [OLEAUT32.31]
8333 * Build type information for an object so it can be called through an
8334 * IDispatch interface.
8337 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8338 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8341 * This call allows an objects methods to be accessed through IDispatch, by
8342 * building an ITypeInfo object that IDispatch can use to call through.
8344 HRESULT WINAPI
CreateDispTypeInfo(
8345 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8346 LCID lcid
, /* [I] Locale Id */
8347 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8349 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8350 ITypeLibImpl
*pTypeLibImpl
;
8351 unsigned int param
, func
;
8352 TLBFuncDesc
*pFuncDesc
;
8356 pTypeLibImpl
= TypeLibImpl_Constructor();
8357 if (!pTypeLibImpl
) return E_FAIL
;
8359 pTypeLibImpl
->TypeInfoCount
= 2;
8360 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8362 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8363 pTIIface
->pTypeLib
= pTypeLibImpl
;
8364 pTIIface
->index
= 0;
8365 pTIIface
->Name
= NULL
;
8366 pTIIface
->dwHelpContext
= -1;
8367 pTIIface
->guid
= NULL
;
8368 pTIIface
->typeattr
.lcid
= lcid
;
8369 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8370 pTIIface
->typeattr
.wMajorVerNum
= 0;
8371 pTIIface
->typeattr
.wMinorVerNum
= 0;
8372 pTIIface
->typeattr
.cbAlignment
= 2;
8373 pTIIface
->typeattr
.cbSizeInstance
= -1;
8374 pTIIface
->typeattr
.cbSizeVft
= -1;
8375 pTIIface
->typeattr
.cFuncs
= 0;
8376 pTIIface
->typeattr
.cImplTypes
= 0;
8377 pTIIface
->typeattr
.cVars
= 0;
8378 pTIIface
->typeattr
.wTypeFlags
= 0;
8379 pTIIface
->hreftype
= 0;
8381 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8382 pFuncDesc
= pTIIface
->funcdescs
;
8383 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8384 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8385 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8386 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8387 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8388 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8389 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8390 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8391 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8392 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8393 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8394 pFuncDesc
->funcdesc
.cScodes
= 0;
8395 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8396 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8397 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8398 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8399 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8400 md
->cArgs
* sizeof(ELEMDESC
));
8401 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8402 for(param
= 0; param
< md
->cArgs
; param
++) {
8403 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8404 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8406 pFuncDesc
->helpcontext
= 0;
8407 pFuncDesc
->HelpStringContext
= 0;
8408 pFuncDesc
->HelpString
= NULL
;
8409 pFuncDesc
->Entry
= NULL
;
8410 list_init(&pFuncDesc
->custdata_list
);
8411 pTIIface
->typeattr
.cFuncs
++;
8415 dump_TypeInfo(pTIIface
);
8417 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8418 pTIClass
->pTypeLib
= pTypeLibImpl
;
8419 pTIClass
->index
= 1;
8420 pTIClass
->Name
= NULL
;
8421 pTIClass
->dwHelpContext
= -1;
8422 pTIClass
->guid
= NULL
;
8423 pTIClass
->typeattr
.lcid
= lcid
;
8424 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8425 pTIClass
->typeattr
.wMajorVerNum
= 0;
8426 pTIClass
->typeattr
.wMinorVerNum
= 0;
8427 pTIClass
->typeattr
.cbAlignment
= 2;
8428 pTIClass
->typeattr
.cbSizeInstance
= -1;
8429 pTIClass
->typeattr
.cbSizeVft
= -1;
8430 pTIClass
->typeattr
.cFuncs
= 0;
8431 pTIClass
->typeattr
.cImplTypes
= 1;
8432 pTIClass
->typeattr
.cVars
= 0;
8433 pTIClass
->typeattr
.wTypeFlags
= 0;
8434 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8436 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8438 ref
= heap_alloc_zero(sizeof(*ref
));
8439 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8440 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8442 dump_TypeInfo(pTIClass
);
8444 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8446 ITypeInfo_AddRef(*pptinfo
);
8447 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8453 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8455 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8457 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8460 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8462 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8464 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8467 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8469 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8471 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8474 static HRESULT WINAPI
ITypeComp_fnBind(
8479 ITypeInfo
** ppTInfo
,
8480 DESCKIND
* pDescKind
,
8483 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8484 const TLBFuncDesc
*pFDesc
;
8485 const TLBVarDesc
*pVDesc
;
8486 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8489 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8491 *pDescKind
= DESCKIND_NONE
;
8492 pBindPtr
->lpfuncdesc
= NULL
;
8495 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8496 pFDesc
= &This
->funcdescs
[fdc
];
8497 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8498 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8501 /* name found, but wrong flags */
8502 hr
= TYPE_E_TYPEMISMATCH
;
8506 if (fdc
< This
->typeattr
.cFuncs
)
8508 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8510 &pBindPtr
->lpfuncdesc
,
8511 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8514 *pDescKind
= DESCKIND_FUNCDESC
;
8515 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8516 ITypeInfo_AddRef(*ppTInfo
);
8519 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, szName
);
8521 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8524 *pDescKind
= DESCKIND_VARDESC
;
8525 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8526 ITypeInfo_AddRef(*ppTInfo
);
8531 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8532 /* recursive search */
8536 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8539 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8540 ITypeInfo_Release(pTInfo
);
8544 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8545 ITypeComp_Release(pTComp
);
8546 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8547 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8549 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8550 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8551 SysFreeString((BSTR
)tmp
);
8555 WARN("Could not search inherited interface!\n");
8557 if (hr
== DISP_E_MEMBERNOTFOUND
)
8559 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8563 static HRESULT WINAPI
ITypeComp_fnBindType(
8567 ITypeInfo
** ppTInfo
,
8568 ITypeComp
** ppTComp
)
8570 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8572 /* strange behaviour (does nothing) but like the
8575 if (!ppTInfo
|| !ppTComp
)
8584 static const ITypeCompVtbl tcompvt
=
8587 ITypeComp_fnQueryInterface
,
8589 ITypeComp_fnRelease
,
8592 ITypeComp_fnBindType
8595 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8596 ICreateTypeLib2
** ppctlib
)
8601 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8603 if (!szFile
) return E_INVALIDARG
;
8605 This
= TypeLibImpl_Constructor();
8607 return E_OUTOFMEMORY
;
8609 This
->lcid
= GetSystemDefaultLCID();
8610 This
->syskind
= syskind
;
8611 This
->ptr_size
= get_ptr_size(syskind
);
8613 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8615 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8616 return E_OUTOFMEMORY
;
8618 lstrcpyW(This
->path
, szFile
);
8620 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8621 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8625 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8626 REFIID riid
, void **object
)
8628 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8630 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8633 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8635 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8637 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8640 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8642 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8644 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8647 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8648 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8650 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8651 ITypeInfoImpl
*info
;
8654 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8656 if (!ctinfo
|| !name
)
8657 return E_INVALIDARG
;
8659 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8661 return TYPE_E_NAMECONFLICT
;
8663 if (This
->typeinfos
)
8664 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8665 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8667 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8669 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8671 info
->pTypeLib
= This
;
8672 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8673 info
->index
= This
->TypeInfoCount
;
8674 info
->typeattr
.typekind
= kind
;
8675 info
->typeattr
.cbAlignment
= 4;
8677 switch (info
->typeattr
.typekind
) {
8679 case TKIND_INTERFACE
:
8680 case TKIND_DISPATCH
:
8682 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
8686 info
->typeattr
.cbSizeInstance
= 0;
8689 info
->typeattr
.cbSizeInstance
= 2;
8692 info
->typeattr
.cbSizeInstance
= -0x75;
8695 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
8696 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
8700 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8701 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8703 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8707 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8709 ++This
->TypeInfoCount
;
8714 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8717 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8719 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8722 return E_INVALIDARG
;
8724 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8729 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8730 WORD majorVerNum
, WORD minorVerNum
)
8732 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8734 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8736 This
->ver_major
= majorVerNum
;
8737 This
->ver_minor
= minorVerNum
;
8742 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8745 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8747 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8749 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8754 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8757 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8759 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8762 return E_INVALIDARG
;
8764 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8769 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8770 LPOLESTR helpFileName
)
8772 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8774 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8777 return E_INVALIDARG
;
8779 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8784 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8787 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8789 TRACE("%p %d\n", This
, helpContext
);
8791 This
->dwHelpContext
= helpContext
;
8796 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8799 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8801 TRACE("%p %x\n", This
, lcid
);
8803 This
->set_lcid
= lcid
;
8808 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8811 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8813 TRACE("%p %x\n", This
, libFlags
);
8815 This
->libflags
= libFlags
;
8820 typedef struct tagWMSFT_SegContents
{
8823 } WMSFT_SegContents
;
8825 typedef struct tagWMSFT_TLBFile
{
8827 WMSFT_SegContents typeinfo_seg
;
8828 WMSFT_SegContents impfile_seg
;
8829 WMSFT_SegContents impinfo_seg
;
8830 WMSFT_SegContents ref_seg
;
8831 WMSFT_SegContents guidhash_seg
;
8832 WMSFT_SegContents guid_seg
;
8833 WMSFT_SegContents namehash_seg
;
8834 WMSFT_SegContents name_seg
;
8835 WMSFT_SegContents string_seg
;
8836 WMSFT_SegContents typdesc_seg
;
8837 WMSFT_SegContents arraydesc_seg
;
8838 WMSFT_SegContents custdata_seg
;
8839 WMSFT_SegContents cdguids_seg
;
8841 WMSFT_SegContents aux_seg
;
8844 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8845 WMSFT_TLBFile
*file
)
8851 file
->string_seg
.len
= 0;
8852 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8855 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8857 return E_UNEXPECTED
;
8859 size
+= sizeof(INT16
);
8861 size
= (size
+ 4) & ~0x3;
8865 file
->string_seg
.len
+= size
;
8867 /* temporarily use str->offset to store the length of the aligned,
8868 * converted string */
8872 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8875 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8878 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8879 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8881 heap_free(file
->string_seg
.data
);
8882 return E_UNEXPECTED
;
8885 *((INT16
*)data
) = size
;
8887 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8891 str
->offset
= last_offs
;
8898 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8899 WMSFT_TLBFile
*file
)
8904 MSFT_NameIntro
*last_intro
= NULL
;
8906 file
->header
.nametablecount
= 0;
8907 file
->header
.nametablechars
= 0;
8909 file
->name_seg
.len
= 0;
8910 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8913 size
= strlenW(str
->str
);
8914 file
->header
.nametablechars
+= size
;
8915 file
->header
.nametablecount
++;
8917 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8919 return E_UNEXPECTED
;
8921 size
+= sizeof(MSFT_NameIntro
);
8923 size
= (size
+ 4) & ~0x3;
8927 file
->name_seg
.len
+= size
;
8929 /* temporarily use str->offset to store the length of the aligned,
8930 * converted string */
8934 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8935 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
8938 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8940 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8942 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8943 data
+ sizeof(MSFT_NameIntro
),
8944 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8946 heap_free(file
->name_seg
.data
);
8947 return E_UNEXPECTED
;
8949 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
8951 intro
->hreftype
= -1; /* TODO? */
8952 intro
->namelen
= size
& 0xFF;
8953 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8954 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
8955 intro
->namelen
|= hash
<< 16;
8956 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
8957 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
8959 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
8960 str
->offset
- size
- sizeof(MSFT_NameIntro
));
8962 /* update str->offset to actual value to use in other
8963 * compilation functions that require positions within
8964 * the string table */
8968 str
->offset
= last_offs
;
8973 last_intro
->hreftype
= 0; /* last one is 0? */
8978 static inline int hash_guid(GUID
*guid
)
8982 for (i
= 0; i
< 8; i
++)
8983 hash
^= ((const short *)guid
)[i
];
8988 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
8991 MSFT_GuidEntry
*entry
;
8993 int hash_key
, *guidhashtab
;
8995 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
8996 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
8998 entry
= file
->guid_seg
.data
;
9000 guidhashtab
= file
->guidhash_seg
.data
;
9001 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9002 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9003 entry
->hreftype
= guid
->hreftype
;
9005 hash_key
= hash_guid(&guid
->guid
);
9006 entry
->next_hash
= guidhashtab
[hash_key
];
9007 guidhashtab
[hash_key
] = offs
;
9009 guid
->offset
= offs
;
9010 offs
+= sizeof(MSFT_GuidEntry
);
9017 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9020 VARTYPE arg_type
= V_VT(value
);
9023 DWORD ret
= file
->custdata_seg
.len
;
9025 if(arg_type
== VT_INT
)
9027 if(arg_type
== VT_UINT
)
9031 if(V_VT(value
) != arg_type
) {
9032 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9034 ERR("VariantChangeType failed: %08x\n", hres
);
9039 /* Check if default value can be stored in-place */
9044 if(V_UI4(&v
) > 0x3ffffff)
9057 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9060 /* have to allocate space in custdata_seg */
9069 /* Construct the data to be allocated */
9072 if(file
->custdata_seg
.data
){
9073 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9074 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9075 file
->custdata_seg
.len
+= sizeof(int) * 2;
9077 file
->custdata_seg
.len
= sizeof(int) * 2;
9078 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9081 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9082 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9084 /* TODO: Check if the encoded data is already present in custdata_seg */
9090 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9093 if(file
->custdata_seg
.data
){
9094 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9095 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9096 file
->custdata_seg
.len
+= len
;
9098 file
->custdata_seg
.len
= len
;
9099 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9102 *((unsigned short *)data
) = V_VT(value
);
9103 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9104 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9105 if(V_BSTR(&v
)[i
] <= 0x7f)
9106 data
[i
+6] = V_BSTR(&v
)[i
];
9110 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9111 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9114 /* TODO: Check if the encoded data is already present in custdata_seg */
9119 FIXME("Argument type not yet handled\n");
9124 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9126 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9128 DWORD offs
= file
->arraydesc_seg
.len
;
9132 /* TODO: we should check for duplicates, but that's harder because each
9133 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9134 * at the library-level) */
9136 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9137 if(!file
->arraydesc_seg
.data
)
9138 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9140 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9141 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9143 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9144 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9145 for(i
= 0; i
< desc
->cDims
; ++i
){
9146 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9147 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9153 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9159 VARTYPE vt
, subtype
;
9170 vt
= desc
->vt
& VT_TYPEMASK
;
9172 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9174 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9175 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9177 *out_size
+= 2 * sizeof(DWORD
);
9178 }else if(vt
== VT_CARRAY
){
9179 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9180 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9182 }else if(vt
== VT_USERDEFINED
){
9183 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9184 encoded
[1] = desc
->u
.hreftype
;
9185 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9187 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9205 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9208 data
= file
->typdesc_seg
.data
;
9209 while(offs
< file
->typdesc_seg
.len
){
9210 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9212 offs
+= sizeof(encoded
);
9215 file
->typdesc_seg
.len
+= sizeof(encoded
);
9216 if(!file
->typdesc_seg
.data
)
9217 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9219 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9221 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9226 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9228 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9229 DWORD ret
= cdguids_seg
->len
, offs
;
9230 MSFT_CDGuid
*cdguid
;
9233 if(list_empty(custdata_list
))
9236 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9237 if(!cdguids_seg
->data
){
9238 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9240 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9241 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9244 offs
= ret
+ sizeof(MSFT_CDGuid
);
9245 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9246 cdguid
->GuidOffset
= cd
->guid
->offset
;
9247 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9248 cdguid
->next
= offs
;
9249 offs
+= sizeof(MSFT_CDGuid
);
9259 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9260 WMSFT_TLBFile
*file
)
9262 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9263 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9264 MSFT_VarRecord
*varrecord
;
9265 MSFT_FuncRecord
*funcrecord
;
9267 DWORD
*name
, *offsets
, offs
;
9269 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9270 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9272 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9274 /* optional fields */
9275 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9276 if(!list_empty(&desc
->custdata_list
))
9277 recorded_size
+= 7 * sizeof(INT
);
9278 else if(desc
->HelpStringContext
!= 0)
9279 recorded_size
+= 6 * sizeof(INT
);
9281 else if(desc
->Entry
)
9282 recorded_size
+= 3 * sizeof(INT
);
9283 else if(desc
->HelpString
)
9284 recorded_size
+= 2 * sizeof(INT
);
9285 else if(desc
->helpcontext
)
9286 recorded_size
+= sizeof(INT
);
9288 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9290 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9291 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9292 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9297 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9300 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9301 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9303 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9305 /* optional fields */
9306 if(desc
->HelpStringContext
!= 0)
9307 recorded_size
+= 5 * sizeof(INT
);
9308 else if(!list_empty(&desc
->custdata_list
))
9309 recorded_size
+= 4 * sizeof(INT
);
9311 else if(desc
->HelpString
)
9312 recorded_size
+= 2 * sizeof(INT
);
9313 else if(desc
->HelpContext
!= 0)
9314 recorded_size
+= sizeof(INT
);
9316 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9319 if(!recorded_size
&& !extra_size
)
9322 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9324 aux_seg
->len
+= recorded_size
+ extra_size
;
9326 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9329 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9331 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9333 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9335 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9338 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9339 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9340 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9341 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9343 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9344 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9345 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9346 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9349 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9354 * ^has_param_defaults
9355 * ^oEntry_is_intresource
9357 funcrecord
->FKCCIC
=
9358 desc
->funcdesc
.funckind
|
9359 (desc
->funcdesc
.invkind
<< 3) |
9360 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9361 (desc
->funcdesc
.callconv
<< 8);
9363 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9364 funcrecord
->FKCCIC
|= 0x2000;
9366 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9367 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9368 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9369 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9372 if(paramdefault_size
> 0)
9373 funcrecord
->FKCCIC
|= 0x1000;
9375 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9376 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9378 /* optional fields */
9380 if(!list_empty(&desc
->custdata_list
)){
9381 size
+= 7 * sizeof(INT
);
9382 funcrecord
->HelpContext
= desc
->helpcontext
;
9383 if(desc
->HelpString
)
9384 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9386 funcrecord
->oHelpString
= -1;
9388 funcrecord
->oEntry
= -1;
9389 else if(IS_INTRESOURCE(desc
->Entry
))
9390 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9392 funcrecord
->oEntry
= desc
->Entry
->offset
;
9393 funcrecord
->res9
= -1;
9394 funcrecord
->resA
= -1;
9395 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9396 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9397 }else if(desc
->HelpStringContext
!= 0){
9398 size
+= 6 * sizeof(INT
);
9399 funcrecord
->HelpContext
= desc
->helpcontext
;
9400 if(desc
->HelpString
)
9401 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9403 funcrecord
->oHelpString
= -1;
9405 funcrecord
->oEntry
= -1;
9406 else if(IS_INTRESOURCE(desc
->Entry
))
9407 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9409 funcrecord
->oEntry
= desc
->Entry
->offset
;
9410 funcrecord
->res9
= -1;
9411 funcrecord
->resA
= -1;
9412 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9413 }else if(desc
->Entry
){
9414 size
+= 3 * sizeof(INT
);
9415 funcrecord
->HelpContext
= desc
->helpcontext
;
9416 if(desc
->HelpString
)
9417 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9419 funcrecord
->oHelpString
= -1;
9421 funcrecord
->oEntry
= -1;
9422 else if(IS_INTRESOURCE(desc
->Entry
))
9423 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9425 funcrecord
->oEntry
= desc
->Entry
->offset
;
9426 }else if(desc
->HelpString
){
9427 size
+= 2 * sizeof(INT
);
9428 funcrecord
->HelpContext
= desc
->helpcontext
;
9429 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9430 }else if(desc
->helpcontext
){
9431 size
+= sizeof(INT
);
9432 funcrecord
->HelpContext
= desc
->helpcontext
;
9435 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9436 size
+= paramdefault_size
;
9438 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9439 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9441 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9442 if(desc
->pParamDesc
[j
].Name
)
9443 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9446 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9448 if(paramdefault_size
){
9449 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9450 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9451 else if(paramdefault_size
)
9456 size
+= sizeof(MSFT_ParameterInfo
);
9459 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9465 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9468 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9469 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9470 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9471 DWORD size
= 5 * sizeof(INT
);
9473 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9474 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9475 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9476 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9478 if(desc
->vardesc
.varkind
== VAR_CONST
){
9479 varrecord
->vardescsize
+= sizeof(VARIANT
);
9480 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9482 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9485 if(desc
->HelpStringContext
!= 0){
9486 size
+= 5 * sizeof(INT
);
9487 varrecord
->HelpContext
= desc
->HelpContext
;
9488 if(desc
->HelpString
)
9489 varrecord
->HelpString
= desc
->HelpString
->offset
;
9491 varrecord
->HelpString
= -1;
9492 varrecord
->res9
= -1;
9493 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9494 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9495 }else if(!list_empty(&desc
->custdata_list
)){
9496 size
+= 4 * sizeof(INT
);
9497 varrecord
->HelpContext
= desc
->HelpContext
;
9498 if(desc
->HelpString
)
9499 varrecord
->HelpString
= desc
->HelpString
->offset
;
9501 varrecord
->HelpString
= -1;
9502 varrecord
->res9
= -1;
9503 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9504 }else if(desc
->HelpString
){
9505 size
+= 2 * sizeof(INT
);
9506 varrecord
->HelpContext
= desc
->HelpContext
;
9507 if(desc
->HelpString
)
9508 varrecord
->HelpString
= desc
->HelpString
->offset
;
9510 varrecord
->HelpString
= -1;
9511 }else if(desc
->HelpContext
!= 0){
9512 size
+= sizeof(INT
);
9513 varrecord
->HelpContext
= desc
->HelpContext
;
9516 varrecord
->Info
= size
| (i
<< 16);
9522 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9525 memid
= (MEMBERID
*)varrecord
;
9526 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9527 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9528 *memid
= desc
->funcdesc
.memid
;
9531 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9532 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9533 *memid
= desc
->vardesc
.memid
;
9537 name
= (UINT
*)memid
;
9538 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9539 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9541 *name
= desc
->Name
->offset
;
9546 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9547 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9549 *name
= desc
->Name
->offset
;
9558 typedef struct tagWMSFT_RefChunk
{
9565 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9567 DWORD offs
= file
->ref_seg
.len
, i
;
9568 WMSFT_RefChunk
*chunk
;
9570 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9571 if(!file
->ref_seg
.data
)
9572 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9574 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9576 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9578 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9579 chunk
->href
= info
->impltypes
[i
].hRef
;
9580 chunk
->res04
= info
->impltypes
[i
].implflags
;
9582 if(i
< info
->typeattr
.cImplTypes
- 1)
9583 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9592 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9596 size
= sizeof(MSFT_TypeInfoBase
);
9599 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9600 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9601 base
->typekind
= TKIND_DISPATCH
;
9603 base
->typekind
= info
->typeattr
.typekind
;
9604 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9605 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
9606 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9611 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
9617 base
->posguid
= info
->guid
->offset
;
9620 base
->flags
= info
->typeattr
.wTypeFlags
;
9622 base
->NameOffset
= info
->Name
->offset
;
9624 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9625 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9627 base
->NameOffset
= -1;
9629 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
9631 base
->docstringoffs
= info
->DocString
->offset
;
9633 base
->docstringoffs
= -1;
9634 base
->helpstringcontext
= info
->dwHelpStringContext
;
9635 base
->helpcontext
= info
->dwHelpContext
;
9636 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9637 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
9638 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
9639 base
->size
= info
->typeattr
.cbSizeInstance
;
9640 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
9641 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9642 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
9643 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9644 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
9646 base
->datatype1
= info
->DllName
->offset
;
9648 base
->datatype1
= -1;
9650 if(info
->typeattr
.cImplTypes
> 0)
9651 base
->datatype1
= info
->impltypes
[0].hRef
;
9653 base
->datatype1
= -1;
9655 base
->datatype2
= index
; /* FIXME: i think there's more here */
9663 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9667 file
->typeinfo_seg
.len
= 0;
9668 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9669 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9670 *junk
= file
->typeinfo_seg
.len
;
9672 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9675 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9676 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9678 file
->aux_seg
.len
= 0;
9679 file
->aux_seg
.data
= NULL
;
9681 file
->typeinfo_seg
.len
= 0;
9682 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9683 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9684 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9685 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9689 typedef struct tagWMSFT_ImpFile
{
9695 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9698 WMSFT_ImpFile
*impfile
;
9700 DWORD last_offs
= 0;
9702 file
->impfile_seg
.len
= 0;
9703 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9707 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9711 path
= implib
->name
;
9712 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9714 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9717 size
+= sizeof(INT16
);
9719 size
= (size
+ 4) & ~0x3;
9723 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9726 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9728 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9729 int strlen
= 0, size
;
9731 impfile
= (WMSFT_ImpFile
*)data
;
9732 impfile
->guid_offs
= implib
->guid
->offset
;
9733 impfile
->lcid
= implib
->lcid
;
9734 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9736 data
+= sizeof(WMSFT_ImpFile
);
9739 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9743 path
= implib
->name
;
9744 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9745 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9747 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9750 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9752 size
= strlen
+ sizeof(INT16
);
9754 size
= (size
+ 4) & ~0x3;
9757 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9760 implib
->offset
= last_offs
;
9761 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9765 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9768 TLBRefType
*ref_type
;
9771 WMSFT_compile_impfile(This
, file
);
9773 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9774 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9776 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9777 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9778 if(ref_type
->index
== TLB_REF_USE_GUID
){
9779 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9780 info
->oGuid
= ref_type
->guid
->offset
;
9782 info
->oGuid
= ref_type
->index
;
9783 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9789 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9791 file
->guidhash_seg
.len
= 0x80;
9792 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9793 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9796 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9798 file
->namehash_seg
.len
= 0x200;
9799 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9800 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9803 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9805 if(contents
&& contents
->len
){
9806 segdir
->offset
= *running_offset
;
9807 segdir
->length
= contents
->len
;
9808 *running_offset
+= segdir
->length
;
9810 segdir
->offset
= -1;
9814 /* TODO: do these ever change? */
9816 segdir
->res0c
= 0xf;
9819 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9823 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9826 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9830 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9832 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9833 base
->memoffset
+= file_len
;
9840 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9842 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9843 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9844 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9845 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9846 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9847 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9848 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9849 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9850 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9851 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9852 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9853 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9854 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9855 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9858 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9860 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9862 DWORD written
, junk_size
, junk_offs
, running_offset
;
9869 TRACE("%p\n", This
);
9871 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
9872 if(This
->typeinfos
[i
]->needs_layout
)
9873 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
9875 memset(&file
, 0, sizeof(file
));
9877 file
.header
.magic1
= 0x5446534D;
9878 file
.header
.magic2
= 0x00010002;
9879 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9880 file
.header
.lcid2
= This
->set_lcid
;
9881 file
.header
.varflags
= 0x40 | This
->syskind
;
9883 file
.header
.varflags
|= 0x10;
9884 if (This
->HelpStringDll
)
9885 file
.header
.varflags
|= HELPDLLFLAG
;
9886 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
9887 file
.header
.flags
= This
->libflags
;
9888 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9889 file
.header
.helpcontext
= This
->dwHelpContext
;
9890 file
.header
.res44
= 0x20;
9891 file
.header
.res48
= 0x80;
9892 file
.header
.dispatchpos
= This
->dispatch_href
;
9894 WMSFT_compile_namehash(This
, &file
);
9895 /* do name and string compilation to get offsets for other compilations */
9896 hres
= WMSFT_compile_names(This
, &file
);
9898 WMSFT_free_file(&file
);
9902 hres
= WMSFT_compile_strings(This
, &file
);
9904 WMSFT_free_file(&file
);
9908 WMSFT_compile_guidhash(This
, &file
);
9909 hres
= WMSFT_compile_guids(This
, &file
);
9911 WMSFT_free_file(&file
);
9916 file
.header
.helpfile
= This
->HelpFile
->offset
;
9918 file
.header
.helpfile
= -1;
9921 file
.header
.helpstring
= This
->DocString
->offset
;
9923 file
.header
.helpstring
= -1;
9925 /* do some more segment compilation */
9926 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9927 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9930 file
.header
.NameOffset
= This
->Name
->offset
;
9932 file
.header
.NameOffset
= -1;
9934 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
9937 file
.header
.posguid
= This
->guid
->offset
;
9939 file
.header
.posguid
= -1;
9941 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9942 if(file
.header
.varflags
& HELPDLLFLAG
)
9943 junk_size
+= sizeof(DWORD
);
9945 junk
= heap_alloc_zero(junk_size
);
9946 if(file
.header
.varflags
& HELPDLLFLAG
){
9947 *junk
= This
->HelpStringDll
->offset
;
9956 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
9957 WMSFT_compile_impinfo(This
, &file
);
9961 TRACE("header at: 0x%x\n", running_offset
);
9962 running_offset
+= sizeof(file
.header
);
9964 TRACE("junk at: 0x%x\n", running_offset
);
9965 running_offset
+= junk_size
;
9967 TRACE("segdir at: 0x%x\n", running_offset
);
9968 running_offset
+= sizeof(file
.segdir
);
9970 TRACE("typeinfo at: 0x%x\n", running_offset
);
9971 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
9973 TRACE("guidhashtab at: 0x%x\n", running_offset
);
9974 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
9976 TRACE("guidtab at: 0x%x\n", running_offset
);
9977 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
9979 TRACE("reftab at: 0x%x\n", running_offset
);
9980 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
9982 TRACE("impinfo at: 0x%x\n", running_offset
);
9983 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
9985 TRACE("impfiles at: 0x%x\n", running_offset
);
9986 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
9988 TRACE("namehashtab at: 0x%x\n", running_offset
);
9989 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
9991 TRACE("nametab at: 0x%x\n", running_offset
);
9992 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
9994 TRACE("stringtab at: 0x%x\n", running_offset
);
9995 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
9997 TRACE("typdesc at: 0x%x\n", running_offset
);
9998 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10000 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10001 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10003 TRACE("custdata at: 0x%x\n", running_offset
);
10004 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10006 TRACE("cdguids at: 0x%x\n", running_offset
);
10007 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10009 TRACE("res0e at: 0x%x\n", running_offset
);
10010 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10012 TRACE("res0f at: 0x%x\n", running_offset
);
10013 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10015 TRACE("aux_seg at: 0x%x\n", running_offset
);
10017 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10019 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10020 FILE_ATTRIBUTE_NORMAL
, 0);
10021 if (outfile
== INVALID_HANDLE_VALUE
){
10022 WMSFT_free_file(&file
);
10024 return TYPE_E_IOERROR
;
10027 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10029 WMSFT_free_file(&file
);
10030 CloseHandle(outfile
);
10032 return TYPE_E_IOERROR
;
10035 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10038 WMSFT_free_file(&file
);
10039 CloseHandle(outfile
);
10040 return TYPE_E_IOERROR
;
10043 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10045 WMSFT_free_file(&file
);
10046 CloseHandle(outfile
);
10047 return TYPE_E_IOERROR
;
10050 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10051 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10052 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10053 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10054 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10055 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10056 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10057 WMSFT_write_segment(outfile
, &file
.name_seg
);
10058 WMSFT_write_segment(outfile
, &file
.string_seg
);
10059 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10060 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10061 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10062 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10063 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10065 WMSFT_free_file(&file
);
10067 CloseHandle(outfile
);
10072 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10075 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10076 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10080 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10081 REFGUID guid
, VARIANT
*varVal
)
10083 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10086 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10088 if (!guid
|| !varVal
)
10089 return E_INVALIDARG
;
10091 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10093 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10096 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10097 ULONG helpStringContext
)
10099 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10100 FIXME("%p %u - stub\n", This
, helpStringContext
);
10104 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10107 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10108 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10111 return E_INVALIDARG
;
10113 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10118 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10119 ICreateTypeLib2_fnQueryInterface
,
10120 ICreateTypeLib2_fnAddRef
,
10121 ICreateTypeLib2_fnRelease
,
10122 ICreateTypeLib2_fnCreateTypeInfo
,
10123 ICreateTypeLib2_fnSetName
,
10124 ICreateTypeLib2_fnSetVersion
,
10125 ICreateTypeLib2_fnSetGuid
,
10126 ICreateTypeLib2_fnSetDocString
,
10127 ICreateTypeLib2_fnSetHelpFileName
,
10128 ICreateTypeLib2_fnSetHelpContext
,
10129 ICreateTypeLib2_fnSetLcid
,
10130 ICreateTypeLib2_fnSetLibFlags
,
10131 ICreateTypeLib2_fnSaveAllChanges
,
10132 ICreateTypeLib2_fnDeleteTypeInfo
,
10133 ICreateTypeLib2_fnSetCustData
,
10134 ICreateTypeLib2_fnSetHelpStringContext
,
10135 ICreateTypeLib2_fnSetHelpStringDll
10138 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10139 REFIID riid
, void **object
)
10141 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10143 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10146 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10148 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10150 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10153 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10155 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10157 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10160 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10163 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10165 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10167 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10172 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10175 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10179 TRACE("%p %x\n", This
, typeFlags
);
10181 if (typeFlags
& TYPEFLAG_FDUAL
) {
10182 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10184 ITypeInfo
*dispatch
;
10188 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10192 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10193 ITypeLib_Release(stdole
);
10197 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10198 ITypeInfo_Release(dispatch
);
10203 old_flags
= This
->typeattr
.wTypeFlags
;
10204 This
->typeattr
.wTypeFlags
= typeFlags
;
10206 hres
= ICreateTypeInfo2_LayOut(iface
);
10207 if (FAILED(hres
)) {
10208 This
->typeattr
.wTypeFlags
= old_flags
;
10215 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10218 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10220 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10223 return E_INVALIDARG
;
10225 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10230 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10233 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10235 TRACE("%p %d\n", This
, helpContext
);
10237 This
->dwHelpContext
= helpContext
;
10242 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10243 WORD majorVerNum
, WORD minorVerNum
)
10245 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10247 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10249 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10250 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10255 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10256 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10258 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10260 ITypeLib
*container
;
10261 TLBRefType
*ref_type
;
10263 TYPEATTR
*typeattr
;
10267 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10269 if (!typeInfo
|| !refType
)
10270 return E_INVALIDARG
;
10272 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10276 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10277 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10279 ITypeLib_Release(container
);
10281 *refType
= target
->hreftype
;
10286 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10287 if (FAILED(hres
)) {
10288 ITypeLib_Release(container
);
10292 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10293 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10294 implib
->lcid
== libattr
->lcid
&&
10295 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10296 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10300 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10301 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10303 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10304 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10305 implib
->name
= SysAllocString(our_container
->path
);
10307 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10308 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10310 implib
->name
= NULL
;
10311 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10315 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10316 implib
->lcid
= libattr
->lcid
;
10317 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10318 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10320 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10323 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10324 ITypeLib_Release(container
);
10326 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10331 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10332 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10333 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10334 ref_type
->tkind
== typeattr
->typekind
)
10339 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10340 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10342 ref_type
->tkind
= typeattr
->typekind
;
10343 ref_type
->pImpTLInfo
= implib
;
10344 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10346 ref_type
->index
= TLB_REF_USE_GUID
;
10348 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10350 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10353 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10355 *refType
= ref_type
->reference
| 0x1;
10357 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10358 This
->pTypeLib
->dispatch_href
= *refType
;
10363 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10364 UINT index
, FUNCDESC
*funcDesc
)
10366 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10367 TLBFuncDesc tmp_func_desc
, *func_desc
;
10372 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10374 if (!funcDesc
|| funcDesc
->oVft
& 3)
10375 return E_INVALIDARG
;
10377 switch (This
->typeattr
.typekind
) {
10379 if (funcDesc
->funckind
!= FUNC_STATIC
)
10380 return TYPE_E_BADMODULEKIND
;
10382 case TKIND_DISPATCH
:
10383 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10384 return TYPE_E_BADMODULEKIND
;
10387 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10388 return TYPE_E_BADMODULEKIND
;
10391 if (index
> This
->typeattr
.cFuncs
)
10392 return TYPE_E_ELEMENTNOTFOUND
;
10394 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10395 !funcDesc
->cParams
)
10396 return TYPE_E_INCONSISTENTPROPFUNCS
;
10399 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10400 funcDesc
->oVft
% 8 != 0)
10401 return E_INVALIDARG
;
10404 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10405 TLBFuncDesc_Constructor(&tmp_func_desc
);
10407 tmp_func_desc
.funcdesc
= *funcDesc
;
10409 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10410 tmp_func_desc
.funcdesc
.oVft
|= 1;
10412 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10413 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10414 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10416 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10417 tmp_func_desc
.funcdesc
.cScodes
= 0;
10420 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10421 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10422 buf_size
+= sizeof(ELEMDESC
);
10423 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10425 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10426 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10428 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10429 if (FAILED(hres
)) {
10430 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10431 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10435 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10436 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10437 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10438 if (FAILED(hres
)) {
10439 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10440 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10443 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10444 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10445 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10446 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10447 if (FAILED(hres
)) {
10448 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10449 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10455 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10457 if (This
->funcdescs
) {
10458 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10459 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10461 if (index
< This
->typeattr
.cFuncs
) {
10462 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10463 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10464 func_desc
= This
->funcdescs
+ index
;
10466 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10468 /* move custdata lists to the new memory location */
10469 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10471 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10472 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10473 list_init(&fd
->custdata_list
);
10475 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10476 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10481 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10483 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10484 list_init(&func_desc
->custdata_list
);
10486 ++This
->typeattr
.cFuncs
;
10488 This
->needs_layout
= TRUE
;
10493 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10494 UINT index
, HREFTYPE refType
)
10496 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10497 TLBImplType
*impl_type
;
10500 TRACE("%p %u %d\n", This
, index
, refType
);
10502 switch(This
->typeattr
.typekind
){
10503 case TKIND_COCLASS
: {
10505 FIXME("Unhandled index: -1\n");
10509 if(index
!= This
->typeattr
.cImplTypes
)
10510 return TYPE_E_ELEMENTNOTFOUND
;
10514 case TKIND_INTERFACE
:
10515 case TKIND_DISPATCH
:
10516 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10517 return TYPE_E_ELEMENTNOTFOUND
;
10520 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10524 if (This
->impltypes
){
10527 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10528 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10530 if (index
< This
->typeattr
.cImplTypes
) {
10531 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10532 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10533 impl_type
= This
->impltypes
+ index
;
10535 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10537 /* move custdata lists to the new memory location */
10538 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10540 TLBImplType
*it
= &This
->impltypes
[i
];
10541 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10542 list_init(&it
->custdata_list
);
10544 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10545 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10550 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10552 memset(impl_type
, 0, sizeof(TLBImplType
));
10553 TLBImplType_Constructor(impl_type
);
10554 impl_type
->hRef
= refType
;
10556 ++This
->typeattr
.cImplTypes
;
10558 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10559 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10561 hres
= ICreateTypeInfo2_LayOut(iface
);
10568 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10569 UINT index
, INT implTypeFlags
)
10571 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10572 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10574 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10576 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10577 return TYPE_E_BADMODULEKIND
;
10579 if (index
>= This
->typeattr
.cImplTypes
)
10580 return TYPE_E_ELEMENTNOTFOUND
;
10582 impl_type
->implflags
= implTypeFlags
;
10587 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10590 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10592 TRACE("%p %d\n", This
, alignment
);
10594 This
->typeattr
.cbAlignment
= alignment
;
10599 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10602 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10604 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10607 return E_INVALIDARG
;
10609 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10611 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10616 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10617 UINT index
, VARDESC
*varDesc
)
10619 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10620 TLBVarDesc
*var_desc
;
10622 TRACE("%p %u %p\n", This
, index
, varDesc
);
10624 if (This
->vardescs
){
10627 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10628 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
10630 if (index
< This
->typeattr
.cVars
) {
10631 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10632 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
10633 var_desc
= This
->vardescs
+ index
;
10635 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
10637 /* move custdata lists to the new memory location */
10638 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
10640 TLBVarDesc
*var
= &This
->vardescs
[i
];
10641 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10642 list_init(&var
->custdata_list
);
10644 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10645 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10650 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10652 TLBVarDesc_Constructor(var_desc
);
10653 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10654 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10656 ++This
->typeattr
.cVars
;
10658 This
->needs_layout
= TRUE
;
10663 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10664 UINT index
, LPOLESTR
*names
, UINT numNames
)
10666 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10667 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10670 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10673 return E_INVALIDARG
;
10675 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
10676 return TYPE_E_ELEMENTNOTFOUND
;
10678 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10679 if(numNames
> func_desc
->funcdesc
.cParams
)
10680 return TYPE_E_ELEMENTNOTFOUND
;
10682 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10683 return TYPE_E_ELEMENTNOTFOUND
;
10685 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
10686 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10687 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10688 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10689 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10690 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10692 return TYPE_E_AMBIGUOUSNAME
;
10696 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10698 for (i
= 1; i
< numNames
; ++i
) {
10699 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10700 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10706 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10707 UINT index
, LPOLESTR name
)
10709 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10711 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10714 return E_INVALIDARG
;
10716 if(index
>= This
->typeattr
.cVars
)
10717 return TYPE_E_ELEMENTNOTFOUND
;
10719 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10723 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10724 TYPEDESC
*tdescAlias
)
10726 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10729 TRACE("%p %p\n", This
, tdescAlias
);
10732 return E_INVALIDARG
;
10734 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
10735 return TYPE_E_BADMODULEKIND
;
10737 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
10741 heap_free(This
->tdescAlias
);
10742 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10743 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10748 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10749 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10751 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10752 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10756 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10757 UINT index
, LPOLESTR docString
)
10759 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10760 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10762 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10765 return E_INVALIDARG
;
10767 if(index
>= This
->typeattr
.cFuncs
)
10768 return TYPE_E_ELEMENTNOTFOUND
;
10770 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10775 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10776 UINT index
, LPOLESTR docString
)
10778 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10779 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10781 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10784 return E_INVALIDARG
;
10786 if(index
>= This
->typeattr
.cVars
)
10787 return TYPE_E_ELEMENTNOTFOUND
;
10789 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10794 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10795 UINT index
, DWORD helpContext
)
10797 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10798 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10800 TRACE("%p %u %d\n", This
, index
, helpContext
);
10802 if(index
>= This
->typeattr
.cFuncs
)
10803 return TYPE_E_ELEMENTNOTFOUND
;
10805 func_desc
->helpcontext
= helpContext
;
10810 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10811 UINT index
, DWORD helpContext
)
10813 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10814 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10816 TRACE("%p %u %d\n", This
, index
, helpContext
);
10818 if(index
>= This
->typeattr
.cVars
)
10819 return TYPE_E_ELEMENTNOTFOUND
;
10821 var_desc
->HelpContext
= helpContext
;
10826 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10827 UINT index
, BSTR bstrMops
)
10829 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10830 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10834 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10837 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10839 TRACE("%p %p\n", This
, idlDesc
);
10842 return E_INVALIDARG
;
10844 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
10845 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10850 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10852 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10854 TLBFuncDesc
*func_desc
;
10855 UINT user_vft
= 0, i
, depth
= 0;
10856 HRESULT hres
= S_OK
;
10858 TRACE("%p\n", This
);
10860 This
->needs_layout
= FALSE
;
10862 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10866 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
10871 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10873 if (SUCCEEDED(hres
)) {
10874 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10876 if (SUCCEEDED(hres
)) {
10877 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10878 if (FAILED(hres
)) {
10879 ITypeInfo_Release(inh
);
10880 ITypeInfo_Release(tinfo
);
10883 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
10884 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10888 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10889 if(SUCCEEDED(hres
)){
10891 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10892 if(SUCCEEDED(hres
)){
10893 ITypeInfo_Release(inh
);
10897 }while(SUCCEEDED(hres
));
10900 ITypeInfo_Release(inh
);
10901 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10902 This
->typeattr
.cbSizeVft
= 0;
10905 ITypeInfo_Release(tinfo
);
10908 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10909 This
->typeattr
.cbSizeVft
= 0;
10912 ITypeInfo_Release(tinfo
);
10915 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
10916 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10918 This
->typeattr
.cbSizeVft
= 0;
10920 func_desc
= This
->funcdescs
;
10922 while (i
< This
->typeattr
.cFuncs
) {
10923 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10924 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
10926 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10927 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10929 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
10931 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10934 BOOL reset
= FALSE
;
10936 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10938 iter
= This
->funcdescs
;
10939 while (j
< This
->typeattr
.cFuncs
) {
10940 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10942 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
10945 ++func_desc
->funcdesc
.memid
;
10946 iter
= This
->funcdescs
;
10959 if (user_vft
> This
->typeattr
.cbSizeVft
)
10960 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
10962 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
10963 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
10964 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
10966 BOOL reset
= FALSE
;
10969 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
10971 iter
= This
->vardescs
;
10972 while (j
< This
->typeattr
.cVars
) {
10973 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
10975 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
10978 ++var_desc
->vardesc
.memid
;
10979 iter
= This
->vardescs
;
10989 ITypeInfo_Release(tinfo
);
10993 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
10996 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10997 FIXME("%p %u - stub\n", This
, index
);
11001 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11002 MEMBERID memid
, INVOKEKIND invKind
)
11004 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11005 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11009 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11012 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11013 FIXME("%p %u - stub\n", This
, index
);
11017 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11020 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11021 FIXME("%p %x - stub\n", This
, memid
);
11025 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11028 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11029 FIXME("%p %u - stub\n", This
, index
);
11033 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11034 REFGUID guid
, VARIANT
*varVal
)
11038 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11040 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11042 if (!guid
|| !varVal
)
11043 return E_INVALIDARG
;
11045 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11047 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11050 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11051 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11053 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11054 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11058 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11059 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11061 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11062 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11066 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11067 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11069 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11070 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11074 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11075 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11077 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11078 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11082 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11083 ULONG helpStringContext
)
11085 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11087 TRACE("%p %u\n", This
, helpStringContext
);
11089 This
->dwHelpStringContext
= helpStringContext
;
11094 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11095 UINT index
, ULONG helpStringContext
)
11097 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11098 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11102 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11103 UINT index
, ULONG helpStringContext
)
11105 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11106 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11110 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11112 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11113 FIXME("%p - stub\n", This
);
11117 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11120 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11122 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11125 return E_INVALIDARG
;
11127 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11132 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11133 ICreateTypeInfo2_fnQueryInterface
,
11134 ICreateTypeInfo2_fnAddRef
,
11135 ICreateTypeInfo2_fnRelease
,
11136 ICreateTypeInfo2_fnSetGuid
,
11137 ICreateTypeInfo2_fnSetTypeFlags
,
11138 ICreateTypeInfo2_fnSetDocString
,
11139 ICreateTypeInfo2_fnSetHelpContext
,
11140 ICreateTypeInfo2_fnSetVersion
,
11141 ICreateTypeInfo2_fnAddRefTypeInfo
,
11142 ICreateTypeInfo2_fnAddFuncDesc
,
11143 ICreateTypeInfo2_fnAddImplType
,
11144 ICreateTypeInfo2_fnSetImplTypeFlags
,
11145 ICreateTypeInfo2_fnSetAlignment
,
11146 ICreateTypeInfo2_fnSetSchema
,
11147 ICreateTypeInfo2_fnAddVarDesc
,
11148 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11149 ICreateTypeInfo2_fnSetVarName
,
11150 ICreateTypeInfo2_fnSetTypeDescAlias
,
11151 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11152 ICreateTypeInfo2_fnSetFuncDocString
,
11153 ICreateTypeInfo2_fnSetVarDocString
,
11154 ICreateTypeInfo2_fnSetFuncHelpContext
,
11155 ICreateTypeInfo2_fnSetVarHelpContext
,
11156 ICreateTypeInfo2_fnSetMops
,
11157 ICreateTypeInfo2_fnSetTypeIdldesc
,
11158 ICreateTypeInfo2_fnLayOut
,
11159 ICreateTypeInfo2_fnDeleteFuncDesc
,
11160 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11161 ICreateTypeInfo2_fnDeleteVarDesc
,
11162 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11163 ICreateTypeInfo2_fnDeleteImplType
,
11164 ICreateTypeInfo2_fnSetCustData
,
11165 ICreateTypeInfo2_fnSetFuncCustData
,
11166 ICreateTypeInfo2_fnSetParamCustData
,
11167 ICreateTypeInfo2_fnSetVarCustData
,
11168 ICreateTypeInfo2_fnSetImplTypeCustData
,
11169 ICreateTypeInfo2_fnSetHelpStringContext
,
11170 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11171 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11172 ICreateTypeInfo2_fnInvalidate
,
11173 ICreateTypeInfo2_fnSetName
11176 /******************************************************************************
11177 * ClearCustData (OLEAUT32.171)
11179 * Clear a custom data type's data.
11182 * lpCust [I] The custom data type instance
11187 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11189 if (lpCust
&& lpCust
->cCustData
)
11191 if (lpCust
->prgCustData
)
11195 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11196 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11198 CoTaskMemFree(lpCust
->prgCustData
);
11199 lpCust
->prgCustData
= NULL
;
11201 lpCust
->cCustData
= 0;