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
;
4732 TLBString
*tlbstr
, *tlbstr_next
;
4733 TLBGuid
*tlbguid
, *tlbguid_next
;
4737 /* remove cache entry */
4740 TRACE("removing from cache list\n");
4741 EnterCriticalSection(&cache_section
);
4742 if(This
->entry
.next
)
4743 list_remove(&This
->entry
);
4744 LeaveCriticalSection(&cache_section
);
4745 heap_free(This
->path
);
4747 TRACE(" destroying ITypeLib(%p)\n",This
);
4749 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4750 list_remove(&tlbstr
->entry
);
4751 SysFreeString(tlbstr
->str
);
4755 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4756 list_remove(&tlbstr
->entry
);
4757 SysFreeString(tlbstr
->str
);
4761 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4762 list_remove(&tlbguid
->entry
);
4766 TLB_FreeCustData(&This
->custdata_list
);
4768 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4769 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4770 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4772 heap_free(This
->pTypeDesc
);
4774 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4776 if (pImpLib
->pImpTypeLib
)
4777 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4778 SysFreeString(pImpLib
->name
);
4780 list_remove(&pImpLib
->entry
);
4784 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4786 list_remove(&ref_type
->entry
);
4787 heap_free(ref_type
);
4790 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4791 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4792 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4794 heap_free(This
->typeinfos
);
4802 /* ITypeLib::GetTypeInfoCount
4804 * Returns the number of type descriptions in the type library
4806 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4808 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4809 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4810 return This
->TypeInfoCount
;
4813 /* ITypeLib::GetTypeInfo
4815 * retrieves the specified type description in the library.
4817 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4820 ITypeInfo
**ppTInfo
)
4822 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4824 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4827 return E_INVALIDARG
;
4829 if(index
>= This
->TypeInfoCount
)
4830 return TYPE_E_ELEMENTNOTFOUND
;
4832 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4833 ITypeInfo_AddRef(*ppTInfo
);
4839 /* ITypeLibs::GetTypeInfoType
4841 * Retrieves the type of a type description.
4843 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4848 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4850 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4853 return E_INVALIDARG
;
4855 if(index
>= This
->TypeInfoCount
)
4856 return TYPE_E_ELEMENTNOTFOUND
;
4858 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4863 /* ITypeLib::GetTypeInfoOfGuid
4865 * Retrieves the type description that corresponds to the specified GUID.
4868 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4871 ITypeInfo
**ppTInfo
)
4873 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4876 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4878 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4879 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4880 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4881 ITypeInfo_AddRef(*ppTInfo
);
4886 return TYPE_E_ELEMENTNOTFOUND
;
4889 /* ITypeLib::GetLibAttr
4891 * Retrieves the structure that contains the library's attributes.
4894 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4898 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4900 TRACE("(%p, %p)\n", This
, attr
);
4902 if (!attr
) return E_INVALIDARG
;
4904 *attr
= heap_alloc(sizeof(**attr
));
4905 if (!*attr
) return E_OUTOFMEMORY
;
4907 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4908 (*attr
)->lcid
= This
->set_lcid
;
4909 (*attr
)->syskind
= This
->syskind
;
4910 (*attr
)->wMajorVerNum
= This
->ver_major
;
4911 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4912 (*attr
)->wLibFlags
= This
->libflags
;
4917 /* ITypeLib::GetTypeComp
4919 * Enables a client compiler to bind to a library's types, variables,
4920 * constants, and global functions.
4923 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4925 ITypeComp
**ppTComp
)
4927 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4929 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4930 *ppTComp
= &This
->ITypeComp_iface
;
4931 ITypeComp_AddRef(*ppTComp
);
4936 /* ITypeLib::GetDocumentation
4938 * Retrieves the library's documentation string, the complete Help file name
4939 * and path, and the context identifier for the library Help topic in the Help
4942 * On a successful return all non-null BSTR pointers will have been set,
4945 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4949 BSTR
*pBstrDocString
,
4950 DWORD
*pdwHelpContext
,
4951 BSTR
*pBstrHelpFile
)
4953 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4954 HRESULT result
= E_INVALIDARG
;
4957 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4959 pBstrName
, pBstrDocString
,
4960 pdwHelpContext
, pBstrHelpFile
);
4964 /* documentation for the typelib */
4969 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4977 if (This
->DocString
)
4979 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4983 *pBstrDocString
= NULL
;
4987 *pdwHelpContext
= This
->dwHelpContext
;
4993 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
4997 *pBstrHelpFile
= NULL
;
5004 /* for a typeinfo */
5005 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5007 if(SUCCEEDED(result
))
5009 result
= ITypeInfo_GetDocumentation(pTInfo
,
5013 pdwHelpContext
, pBstrHelpFile
);
5015 ITypeInfo_Release(pTInfo
);
5020 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5022 if (pBstrName
) SysFreeString (*pBstrName
);
5024 return STG_E_INSUFFICIENTMEMORY
;
5029 * Indicates whether a passed-in string contains the name of a type or member
5030 * described in the library.
5033 static HRESULT WINAPI
ITypeLib2_fnIsName(
5039 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5041 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5043 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5047 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5048 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5049 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5050 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5051 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5053 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5054 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5055 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5056 goto ITypeLib2_fnIsName_exit
;
5059 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5060 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5061 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5067 ITypeLib2_fnIsName_exit
:
5068 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5069 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5074 /* ITypeLib::FindName
5076 * Finds occurrences of a type description in a type library. This may be used
5077 * to quickly verify that a name exists in a type library.
5080 static HRESULT WINAPI
ITypeLib2_fnFindName(
5084 ITypeInfo
**ppTInfo
,
5088 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5093 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5095 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5096 return E_INVALIDARG
;
5098 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5099 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5100 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5104 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5105 memid
[count
] = MEMBERID_NIL
;
5106 goto ITypeLib2_fnFindName_exit
;
5109 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5110 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5112 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5113 memid
[count
] = func
->funcdesc
.memid
;
5114 goto ITypeLib2_fnFindName_exit
;
5118 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->typeattr
.cVars
, name
);
5120 memid
[count
] = var
->vardesc
.memid
;
5121 goto ITypeLib2_fnFindName_exit
;
5125 ITypeLib2_fnFindName_exit
:
5126 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5127 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5130 TRACE("found %d typeinfos\n", count
);
5137 /* ITypeLib::ReleaseTLibAttr
5139 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5142 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5144 TLIBATTR
*pTLibAttr
)
5146 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5147 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5148 heap_free(pTLibAttr
);
5151 /* ITypeLib2::GetCustData
5153 * gets the custom data
5155 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5160 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5161 TLBCustData
*pCData
;
5163 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5165 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5167 return TYPE_E_ELEMENTNOTFOUND
;
5169 VariantInit(pVarVal
);
5170 VariantCopy(pVarVal
, &pCData
->data
);
5175 /* ITypeLib2::GetLibStatistics
5177 * Returns statistics about a type library that are required for efficient
5178 * sizing of hash tables.
5181 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5183 ULONG
*pcUniqueNames
,
5184 ULONG
*pcchUniqueNames
)
5186 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5188 FIXME("(%p): stub!\n", This
);
5190 if(pcUniqueNames
) *pcUniqueNames
=1;
5191 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5195 /* ITypeLib2::GetDocumentation2
5197 * Retrieves the library's documentation string, the complete Help file name
5198 * and path, the localization context to use, and the context ID for the
5199 * library Help topic in the Help file.
5202 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5206 BSTR
*pbstrHelpString
,
5207 DWORD
*pdwHelpStringContext
,
5208 BSTR
*pbstrHelpStringDll
)
5210 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5214 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5216 /* the help string should be obtained from the helpstringdll,
5217 * using the _DLLGetDocumentation function, based on the supplied
5218 * lcid. Nice to do sometime...
5222 /* documentation for the typelib */
5224 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5225 if(pdwHelpStringContext
)
5226 *pdwHelpStringContext
=This
->dwHelpContext
;
5227 if(pbstrHelpStringDll
)
5228 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5234 /* for a typeinfo */
5235 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5237 if(SUCCEEDED(result
))
5239 ITypeInfo2
* pTInfo2
;
5240 result
= ITypeInfo_QueryInterface(pTInfo
,
5242 (LPVOID
*) &pTInfo2
);
5244 if(SUCCEEDED(result
))
5246 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5250 pdwHelpStringContext
,
5251 pbstrHelpStringDll
);
5253 ITypeInfo2_Release(pTInfo2
);
5256 ITypeInfo_Release(pTInfo
);
5262 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5264 TLBCustData
*pCData
;
5268 ct
= list_count(custdata_list
);
5270 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5271 if(!pCustData
->prgCustData
)
5272 return E_OUTOFMEMORY
;
5274 pCustData
->cCustData
= ct
;
5276 cdi
= pCustData
->prgCustData
;
5277 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5278 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5279 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5287 /* ITypeLib2::GetAllCustData
5289 * Gets all custom data items for the library.
5292 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5294 CUSTDATA
*pCustData
)
5296 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5297 TRACE("(%p)->(%p)\n", This
, pCustData
);
5298 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5301 static const ITypeLib2Vtbl tlbvt
= {
5302 ITypeLib2_fnQueryInterface
,
5304 ITypeLib2_fnRelease
,
5305 ITypeLib2_fnGetTypeInfoCount
,
5306 ITypeLib2_fnGetTypeInfo
,
5307 ITypeLib2_fnGetTypeInfoType
,
5308 ITypeLib2_fnGetTypeInfoOfGuid
,
5309 ITypeLib2_fnGetLibAttr
,
5310 ITypeLib2_fnGetTypeComp
,
5311 ITypeLib2_fnGetDocumentation
,
5313 ITypeLib2_fnFindName
,
5314 ITypeLib2_fnReleaseTLibAttr
,
5316 ITypeLib2_fnGetCustData
,
5317 ITypeLib2_fnGetLibStatistics
,
5318 ITypeLib2_fnGetDocumentation2
,
5319 ITypeLib2_fnGetAllCustData
5323 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5325 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5327 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5330 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5332 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5334 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5337 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5339 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5341 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5344 static HRESULT WINAPI
ITypeLibComp_fnBind(
5349 ITypeInfo
** ppTInfo
,
5350 DESCKIND
* pDescKind
,
5353 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5354 BOOL typemismatch
= FALSE
;
5357 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5359 *pDescKind
= DESCKIND_NONE
;
5360 pBindPtr
->lptcomp
= NULL
;
5363 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5364 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5365 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5367 /* FIXME: check wFlags here? */
5368 /* FIXME: we should use a hash table to look this info up using lHash
5369 * instead of an O(n) search */
5370 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5371 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5373 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5375 *pDescKind
= DESCKIND_TYPECOMP
;
5376 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5377 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5378 TRACE("module or enum: %s\n", debugstr_w(szName
));
5383 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5384 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5386 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5389 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5390 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5392 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5395 else if (hr
== TYPE_E_TYPEMISMATCH
)
5396 typemismatch
= TRUE
;
5399 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5400 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5402 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5404 ITypeInfo
*subtypeinfo
;
5406 DESCKIND subdesckind
;
5408 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5409 &subtypeinfo
, &subdesckind
, &subbindptr
);
5410 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5412 TYPEDESC tdesc_appobject
;
5413 const VARDESC vardesc_appobject
=
5416 NULL
, /* lpstrSchema */
5431 VAR_STATIC
/* varkind */
5434 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5435 tdesc_appobject
.vt
= VT_USERDEFINED
;
5437 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5439 /* cleanup things filled in by Bind call so we can put our
5440 * application object data in there instead */
5441 switch (subdesckind
)
5443 case DESCKIND_FUNCDESC
:
5444 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5446 case DESCKIND_VARDESC
:
5447 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5452 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5454 if (pTypeInfo
->hreftype
== -1)
5455 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5457 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5461 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5462 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5463 ITypeInfo_AddRef(*ppTInfo
);
5466 else if (hr
== TYPE_E_TYPEMISMATCH
)
5467 typemismatch
= TRUE
;
5473 TRACE("type mismatch %s\n", debugstr_w(szName
));
5474 return TYPE_E_TYPEMISMATCH
;
5478 TRACE("name not found %s\n", debugstr_w(szName
));
5483 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5487 ITypeInfo
** ppTInfo
,
5488 ITypeComp
** ppTComp
)
5490 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5491 ITypeInfoImpl
*info
;
5493 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5495 if(!szName
|| !ppTInfo
|| !ppTComp
)
5496 return E_INVALIDARG
;
5498 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5505 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5506 ITypeInfo_AddRef(*ppTInfo
);
5507 *ppTComp
= &info
->ITypeComp_iface
;
5508 ITypeComp_AddRef(*ppTComp
);
5513 static const ITypeCompVtbl tlbtcvt
=
5516 ITypeLibComp_fnQueryInterface
,
5517 ITypeLibComp_fnAddRef
,
5518 ITypeLibComp_fnRelease
,
5520 ITypeLibComp_fnBind
,
5521 ITypeLibComp_fnBindType
5524 /*================== ITypeInfo(2) Methods ===================================*/
5525 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5527 ITypeInfoImpl
*pTypeInfoImpl
;
5529 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5532 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5533 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5534 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5535 pTypeInfoImpl
->ref
= 0;
5536 pTypeInfoImpl
->hreftype
= -1;
5537 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5538 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5539 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5540 list_init(pTypeInfoImpl
->pcustdata_list
);
5542 TRACE("(%p)\n", pTypeInfoImpl
);
5543 return pTypeInfoImpl
;
5546 /* ITypeInfo::QueryInterface
5548 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5553 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5555 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5558 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5559 IsEqualIID(riid
,&IID_ITypeInfo
)||
5560 IsEqualIID(riid
,&IID_ITypeInfo2
))
5561 *ppvObject
= &This
->ITypeInfo2_iface
;
5562 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5563 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5564 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5565 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5566 *ppvObject
= &This
->ITypeComp_iface
;
5569 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5570 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5573 TRACE("-- Interface: E_NOINTERFACE\n");
5574 return E_NOINTERFACE
;
5577 /* ITypeInfo::AddRef
5579 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5581 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5582 ULONG ref
= InterlockedIncrement(&This
->ref
);
5584 TRACE("(%p)->ref is %u\n",This
, ref
);
5586 if (ref
== 1 /* incremented from 0 */)
5587 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5592 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5596 TRACE("destroying ITypeInfo(%p)\n",This
);
5598 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5601 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5602 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5604 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5605 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5606 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5607 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5609 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5610 heap_free(pFInfo
->pParamDesc
);
5611 TLB_FreeCustData(&pFInfo
->custdata_list
);
5613 heap_free(This
->funcdescs
);
5615 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5617 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5618 if (pVInfo
->vardesc_create
) {
5619 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5620 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5621 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5622 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5624 TLB_FreeCustData(&pVInfo
->custdata_list
);
5626 heap_free(This
->vardescs
);
5628 if(This
->impltypes
){
5629 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5630 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5631 TLB_FreeCustData(&pImpl
->custdata_list
);
5633 heap_free(This
->impltypes
);
5636 TLB_FreeCustData(&This
->custdata_list
);
5641 /* ITypeInfo::Release
5643 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5645 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5646 ULONG ref
= InterlockedDecrement(&This
->ref
);
5648 TRACE("(%p)->(%u)\n",This
, ref
);
5652 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5653 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5654 if (not_attached_to_typelib
)
5656 /* otherwise This will be freed when typelib is freed */
5662 /* ITypeInfo::GetTypeAttr
5664 * Retrieves a TYPEATTR structure that contains the attributes of the type
5668 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5669 LPTYPEATTR
*ppTypeAttr
)
5671 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5674 TRACE("(%p)\n",This
);
5676 size
= sizeof(**ppTypeAttr
);
5677 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5678 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5680 *ppTypeAttr
= heap_alloc(size
);
5682 return E_OUTOFMEMORY
;
5684 **ppTypeAttr
= This
->typeattr
;
5685 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5687 if (This
->tdescAlias
)
5688 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5690 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5691 /* This should include all the inherited funcs */
5692 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5693 /* This is always the size of IDispatch's vtbl */
5694 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5695 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5700 /* ITypeInfo::GetTypeComp
5702 * Retrieves the ITypeComp interface for the type description, which enables a
5703 * client compiler to bind to the type description's members.
5706 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5707 ITypeComp
* *ppTComp
)
5709 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5711 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5713 *ppTComp
= &This
->ITypeComp_iface
;
5714 ITypeComp_AddRef(*ppTComp
);
5718 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5720 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5721 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5722 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5726 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5729 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5730 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5732 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5733 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5734 *buffer
+= sizeof(PARAMDESCEX
);
5735 *pparamdescex_dest
= *pparamdescex_src
;
5736 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5737 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5738 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5739 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5742 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5746 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5748 UINT len
= SysStringLen(str
), i
;
5749 for (i
= 0; i
< len
; ++i
)
5755 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5757 if (V_VT(var
) == VT_INT
)
5758 return VariantChangeType(var
, var
, 0, VT_I4
);
5759 else if (V_VT(var
) == VT_UINT
)
5760 return VariantChangeType(var
, var
, 0, VT_UI4
);
5761 else if (V_VT(var
) == VT_BSTR
)
5762 return TLB_SanitizeBSTR(V_BSTR(var
));
5767 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5769 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5770 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5773 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5777 SIZE_T size
= sizeof(*src
);
5781 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5782 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5783 for (i
= 0; i
< src
->cParams
; i
++)
5785 size
+= sizeof(ELEMDESC
);
5786 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5789 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5790 if (!dest
) return E_OUTOFMEMORY
;
5793 if (dispinterface
) /* overwrite funckind */
5794 dest
->funckind
= FUNC_DISPATCH
;
5795 buffer
= (char *)(dest
+ 1);
5797 dest
->oVft
= dest
->oVft
& 0xFFFC;
5799 if (dest
->cScodes
) {
5800 dest
->lprgscode
= (SCODE
*)buffer
;
5801 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5802 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5804 dest
->lprgscode
= NULL
;
5806 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5809 SysFreeString((BSTR
)dest
);
5813 if (dest
->cParams
) {
5814 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5815 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5816 for (i
= 0; i
< src
->cParams
; i
++)
5818 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5824 /* undo the above actions */
5825 for (i
= i
- 1; i
>= 0; i
--)
5826 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5827 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5828 SysFreeString((BSTR
)dest
);
5832 dest
->lprgelemdescParam
= NULL
;
5834 /* special treatment for dispinterfaces: this makes functions appear
5835 * to return their [retval] value when it is really returning an
5837 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5839 if (dest
->cParams
&&
5840 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5842 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5843 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5845 ERR("elemdesc should have started with VT_PTR instead of:\n");
5847 dump_ELEMDESC(elemdesc
);
5848 return E_UNEXPECTED
;
5851 /* copy last parameter to the return value. we are using a flat
5852 * buffer so there is no danger of leaking memory in
5854 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5856 /* remove the last parameter */
5860 /* otherwise this function is made to appear to have no return
5862 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5870 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5872 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5873 if (var_desc
->varkind
== VAR_CONST
)
5874 VariantClear(var_desc
->u
.lpvarValue
);
5875 SysFreeString((BSTR
)var_desc
);
5878 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5880 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5882 if (index
>= This
->typeattr
.cFuncs
)
5883 return TYPE_E_ELEMENTNOTFOUND
;
5885 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5889 /* internal function to make the inherited interfaces' methods appear
5890 * part of the interface */
5891 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5892 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5894 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5896 UINT implemented_funcs
= 0;
5901 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5905 ITypeInfo
*pSubTypeInfo
;
5908 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5912 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5915 &sub_funcs
, hrefoffset
);
5916 implemented_funcs
+= sub_funcs
;
5917 ITypeInfo_Release(pSubTypeInfo
);
5920 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5924 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5928 if (index
< implemented_funcs
)
5929 return E_INVALIDARG
;
5930 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5934 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5936 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5939 switch (pTypeDesc
->vt
)
5941 case VT_USERDEFINED
:
5942 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5946 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5949 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5957 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5960 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5961 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5962 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5965 /* ITypeInfo::GetFuncDesc
5967 * Retrieves the FUNCDESC structure that contains information about a
5968 * specified function.
5971 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5972 LPFUNCDESC
*ppFuncDesc
)
5974 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5975 const FUNCDESC
*internal_funcdesc
;
5977 UINT hrefoffset
= 0;
5979 TRACE("(%p) index %d\n", This
, index
);
5982 return E_INVALIDARG
;
5984 if (This
->needs_layout
)
5985 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5987 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5988 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5989 &internal_funcdesc
, NULL
,
5992 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5993 &internal_funcdesc
);
5996 WARN("description for function %d not found\n", index
);
6000 hr
= TLB_AllocAndInitFuncDesc(
6003 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6005 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
6006 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6008 TRACE("-- 0x%08x\n", hr
);
6012 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6016 SIZE_T size
= sizeof(*src
);
6019 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6020 if (src
->varkind
== VAR_CONST
)
6021 size
+= sizeof(VARIANT
);
6022 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6024 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6025 if (!dest
) return E_OUTOFMEMORY
;
6028 buffer
= (char *)(dest
+ 1);
6029 if (src
->lpstrSchema
)
6032 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6033 len
= strlenW(src
->lpstrSchema
);
6034 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6035 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6038 if (src
->varkind
== VAR_CONST
)
6042 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6043 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6044 buffer
+= sizeof(VARIANT
);
6045 VariantInit(dest
->u
.lpvarValue
);
6046 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6049 SysFreeString((BSTR
)dest
);
6053 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6056 if (src
->varkind
== VAR_CONST
)
6057 VariantClear(dest
->u
.lpvarValue
);
6058 SysFreeString((BSTR
)dest
);
6065 /* ITypeInfo::GetVarDesc
6067 * Retrieves a VARDESC structure that describes the specified variable.
6070 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6071 LPVARDESC
*ppVarDesc
)
6073 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6074 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6076 TRACE("(%p) index %d\n", This
, index
);
6078 if(index
>= This
->typeattr
.cVars
)
6079 return TYPE_E_ELEMENTNOTFOUND
;
6081 if (This
->needs_layout
)
6082 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6084 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6087 /* ITypeInfo_GetNames
6089 * Retrieves the variable with the specified member ID (or the name of the
6090 * property or method and its parameters) that correspond to the specified
6093 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6094 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6096 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6097 const TLBFuncDesc
*pFDesc
;
6098 const TLBVarDesc
*pVDesc
;
6100 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6103 return E_INVALIDARG
;
6107 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
6110 if(!cMaxNames
|| !pFDesc
->Name
)
6113 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6116 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6117 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6119 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6125 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
6128 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6133 if(This
->impltypes
&&
6134 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
6135 /* recursive search */
6138 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6139 if(SUCCEEDED(result
))
6141 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6142 ITypeInfo_Release(pTInfo
);
6145 WARN("Could not search inherited interface!\n");
6149 WARN("no names found\n");
6152 return TYPE_E_ELEMENTNOTFOUND
;
6158 /* ITypeInfo::GetRefTypeOfImplType
6160 * If a type description describes a COM class, it retrieves the type
6161 * description of the implemented interface types. For an interface,
6162 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6166 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6171 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6174 TRACE("(%p) index %d\n", This
, index
);
6175 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6179 /* only valid on dual interfaces;
6180 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6183 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6189 hr
= TYPE_E_ELEMENTNOTFOUND
;
6192 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6194 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6195 *pRefType
= This
->pTypeLib
->dispatch_href
;
6199 if(index
>= This
->typeattr
.cImplTypes
)
6200 hr
= TYPE_E_ELEMENTNOTFOUND
;
6202 *pRefType
= This
->impltypes
[index
].hRef
;
6203 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6211 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6213 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6219 /* ITypeInfo::GetImplTypeFlags
6221 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6222 * or base interface in a type description.
6224 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6225 UINT index
, INT
*pImplTypeFlags
)
6227 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6229 TRACE("(%p) index %d\n", This
, index
);
6232 return E_INVALIDARG
;
6234 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6235 *pImplTypeFlags
= 0;
6239 if(index
>= This
->typeattr
.cImplTypes
)
6240 return TYPE_E_ELEMENTNOTFOUND
;
6242 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6248 * Maps between member names and member IDs, and parameter names and
6251 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6252 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6254 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6255 const TLBVarDesc
*pVDesc
;
6259 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6262 /* init out parameters in case of failure */
6263 for (i
= 0; i
< cNames
; i
++)
6264 pMemId
[i
] = MEMBERID_NIL
;
6266 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6268 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6269 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6270 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6271 for(i
=1; i
< cNames
; i
++){
6272 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6273 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6275 if( j
<pFDesc
->funcdesc
.cParams
)
6278 ret
=DISP_E_UNKNOWNNAME
;
6280 TRACE("-- 0x%08x\n", ret
);
6284 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, *rgszNames
);
6287 *pMemId
= pVDesc
->vardesc
.memid
;
6290 /* not found, see if it can be found in an inherited interface */
6291 if(This
->impltypes
) {
6292 /* recursive search */
6294 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6296 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6297 ITypeInfo_Release(pTInfo
);
6300 WARN("Could not search inherited interface!\n");
6302 WARN("no names found\n");
6303 return DISP_E_UNKNOWNNAME
;
6309 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6310 __ASM_GLOBAL_FUNC( call_method
,
6312 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6313 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6314 "movl %esp,%ebp\n\t"
6315 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6317 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6319 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6320 "movl 12(%ebp),%edx\n\t"
6321 "movl %esp,%edi\n\t"
6324 "subl %edx,%edi\n\t"
6325 "andl $~15,%edi\n\t"
6326 "movl %edi,%esp\n\t"
6327 "movl 12(%ebp),%ecx\n\t"
6328 "movl 16(%ebp),%esi\n\t"
6331 "1:\tcall *8(%ebp)\n\t"
6332 "subl %esp,%edi\n\t"
6333 "movl 20(%ebp),%ecx\n\t"
6334 "movl %edi,(%ecx)\n\t"
6335 "leal -8(%ebp),%esp\n\t"
6337 __ASM_CFI(".cfi_same_value %edi\n\t")
6339 __ASM_CFI(".cfi_same_value %esi\n\t")
6341 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6342 __ASM_CFI(".cfi_same_value %ebp\n\t")
6345 /* same function but returning floating point */
6346 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6348 /* ITypeInfo::Invoke
6350 * Invokes a method, or accesses a property of an object, that implements the
6351 * interface described by the type description.
6354 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6358 if (TRACE_ON(ole
)) {
6360 TRACE("Calling %p(",func
);
6361 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6362 if (nrargs
> 30) TRACE("...");
6369 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6372 FIXME("unsupported calling convention %d\n",callconv
);
6376 TRACE("returns %08x\n",res
);
6380 #elif defined(__x86_64__)
6382 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6383 __ASM_GLOBAL_FUNC( call_method
,
6385 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6386 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6387 "movq %rsp,%rbp\n\t"
6388 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6390 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6392 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6393 "movq %rcx,%rax\n\t"
6396 "cmovgq %rdx,%rcx\n\t"
6397 "leaq 0(,%rcx,8),%rdx\n\t"
6398 "subq %rdx,%rsp\n\t"
6399 "andq $~15,%rsp\n\t"
6400 "movq %rsp,%rdi\n\t"
6403 "movq 0(%rsp),%rcx\n\t"
6404 "movq 8(%rsp),%rdx\n\t"
6405 "movq 16(%rsp),%r8\n\t"
6406 "movq 24(%rsp),%r9\n\t"
6407 "movq 0(%rsp),%xmm0\n\t"
6408 "movq 8(%rsp),%xmm1\n\t"
6409 "movq 16(%rsp),%xmm2\n\t"
6410 "movq 24(%rsp),%xmm3\n\t"
6412 "leaq -16(%rbp),%rsp\n\t"
6414 __ASM_CFI(".cfi_same_value %rdi\n\t")
6416 __ASM_CFI(".cfi_same_value %rsi\n\t")
6417 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6419 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6420 __ASM_CFI(".cfi_same_value %rbp\n\t")
6423 /* same function but returning floating point */
6424 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6426 #endif /* __x86_64__ */
6428 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6431 ITypeInfo
*tinfo2
= NULL
;
6432 TYPEATTR
*tattr
= NULL
;
6434 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6437 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6439 tdesc
->u
.hreftype
, hr
);
6442 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6445 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6446 ITypeInfo_Release(tinfo2
);
6450 switch (tattr
->typekind
)
6457 tdesc
= &tattr
->tdescAlias
;
6458 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6461 case TKIND_INTERFACE
:
6462 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6468 case TKIND_DISPATCH
:
6477 FIXME("TKIND_RECORD unhandled.\n");
6482 FIXME("TKIND_UNION unhandled.\n");
6487 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6491 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6492 ITypeInfo_Release(tinfo2
);
6496 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6500 /* enforce only one level of pointer indirection */
6501 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6503 tdesc
= tdesc
->u
.lptdesc
;
6505 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6506 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6507 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6508 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6509 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6511 VARTYPE vt_userdefined
= 0;
6512 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6513 if (tdesc
->vt
== VT_PTR
)
6515 vt_userdefined
= VT_BYREF
;
6516 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6518 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6520 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6521 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6523 *vt
|= vt_userdefined
;
6535 case VT_USERDEFINED
:
6536 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6543 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6544 hr
= DISP_E_BADVARTYPE
;
6548 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6563 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6569 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6573 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6575 ITypeInfo_Release(tinfo2
);
6579 switch(tattr
->typekind
) {
6581 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6584 case TKIND_INTERFACE
:
6585 case TKIND_DISPATCH
:
6586 *guid
= tattr
->guid
;
6590 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6591 hres
= E_UNEXPECTED
;
6594 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6595 ITypeInfo_Release(tinfo2
);
6599 /***********************************************************************
6600 * DispCallFunc (OLEAUT32.@)
6602 * Invokes a function of the specified calling convention, passing the
6603 * specified arguments and returns the result.
6606 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6607 * oVft [I] The offset in the vtable. See notes.
6608 * cc [I] Calling convention of the function to call.
6609 * vtReturn [I] The return type of the function.
6610 * cActuals [I] Number of parameters.
6611 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6612 * prgpvarg [I] The arguments to pass.
6613 * pvargResult [O] The return value of the function. Can be NULL.
6617 * Failure: HRESULT code.
6620 * The HRESULT return value of this function is not affected by the return
6621 * value of the user supplied function, which is returned in pvargResult.
6623 * If pvInstance is NULL then a non-object function is to be called and oVft
6624 * is the address of the function to call.
6626 * The cc parameter can be one of the following values:
6639 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6640 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6643 int argspos
, stack_offset
;
6648 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6649 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6650 pvargResult
, V_VT(pvargResult
));
6652 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6654 FIXME("unsupported calling convention %d\n",cc
);
6655 return E_INVALIDARG
;
6658 /* maximum size for an argument is sizeof(VARIANT) */
6659 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6661 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6665 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6666 func
= vtable
[oVft
/sizeof(void *)];
6667 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6669 else func
= (void *)oVft
;
6671 for (i
= 0; i
< cActuals
; i
++)
6673 VARIANT
*arg
= prgpvarg
[i
];
6684 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6685 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6689 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6690 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6692 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6693 args
[argspos
++] = V_BOOL(arg
);
6696 args
[argspos
++] = V_UI4(arg
);
6699 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6705 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6708 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6712 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6716 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6717 call_method( func
, argspos
, args
, &stack_offset
);
6722 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6725 WARN("invalid return type %u\n", vtReturn
);
6727 return E_INVALIDARG
;
6729 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6733 if (stack_offset
&& cc
== CC_STDCALL
)
6735 WARN( "stack pointer off by %d\n", stack_offset
);
6736 return DISP_E_BADCALLEE
;
6738 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6739 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6742 #elif defined(__x86_64__)
6748 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6749 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6750 pvargResult
, V_VT(pvargResult
));
6752 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6754 FIXME("unsupported calling convention %d\n",cc
);
6755 return E_INVALIDARG
;
6758 /* maximum size for an argument is sizeof(DWORD_PTR) */
6759 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6761 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6765 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6766 func
= vtable
[oVft
/sizeof(void *)];
6767 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6769 else func
= (void *)oVft
;
6771 for (i
= 0; i
< cActuals
; i
++)
6773 VARIANT
*arg
= prgpvarg
[i
];
6779 args
[argspos
++] = (ULONG_PTR
)arg
;
6781 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6782 args
[argspos
++] = V_BOOL(arg
);
6785 args
[argspos
++] = V_UI8(arg
);
6788 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6794 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6798 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6802 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6803 call_method( func
, argspos
, args
);
6806 WARN("invalid return type %u\n", vtReturn
);
6808 return E_INVALIDARG
;
6810 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6814 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6815 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6819 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6820 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6825 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6827 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6830 #define INVBUF_ELEMENT_SIZE \
6831 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6832 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6833 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6834 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6835 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6836 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6837 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6838 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6840 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6845 DISPPARAMS
*pDispParams
,
6846 VARIANT
*pVarResult
,
6847 EXCEPINFO
*pExcepInfo
,
6850 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6852 unsigned int var_index
;
6855 const TLBFuncDesc
*pFuncInfo
;
6858 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6859 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6862 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6863 return DISP_E_MEMBERNOTFOUND
;
6867 ERR("NULL pDispParams not allowed\n");
6868 return E_INVALIDARG
;
6871 dump_DispParms(pDispParams
);
6873 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6875 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6876 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6877 return E_INVALIDARG
;
6880 /* we do this instead of using GetFuncDesc since it will return a fake
6881 * FUNCDESC for dispinterfaces and we want the real function description */
6882 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
6883 pFuncInfo
= &This
->funcdescs
[fdc
];
6884 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6885 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6886 !func_restricted( &pFuncInfo
->funcdesc
))
6890 if (fdc
< This
->typeattr
.cFuncs
) {
6891 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6895 TRACE("invoking:\n");
6896 dump_TLBFuncDescOne(pFuncInfo
);
6899 switch (func_desc
->funckind
) {
6900 case FUNC_PUREVIRTUAL
:
6901 case FUNC_VIRTUAL
: {
6902 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6904 VARIANT retval
; /* pointer for storing byref retvals in */
6905 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6906 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6907 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6908 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6909 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6910 UINT vargs_converted
=0;
6914 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6916 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6918 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6919 hres
= DISP_E_PARAMNOTFOUND
;
6924 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6926 ERR("functions with the vararg attribute do not support named arguments\n");
6927 hres
= DISP_E_NONAMEDARGS
;
6931 for (i
= 0; i
< func_desc
->cParams
; i
++)
6933 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6934 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6939 TRACE("changing args\n");
6940 for (i
= 0; i
< func_desc
->cParams
; i
++)
6942 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6943 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6944 VARIANTARG
*src_arg
;
6946 if (wParamFlags
& PARAMFLAG_FLCID
)
6949 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6951 V_I4(arg
) = This
->pTypeLib
->lcid
;
6960 for (j
= 0; j
< cNamedArgs
; j
++)
6961 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6963 src_arg
= &pDispParams
->rgvarg
[j
];
6968 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6970 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6974 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6976 /* under most conditions the caller is not allowed to
6977 * pass in a dispparam arg in the index of what would be
6978 * the retval parameter. however, there is an exception
6979 * where the extra parameter is used in an extra
6980 * IDispatch::Invoke below */
6981 if ((i
< pDispParams
->cArgs
) &&
6982 ((func_desc
->cParams
!= 1) || !pVarResult
||
6983 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
6985 hres
= DISP_E_BADPARAMCOUNT
;
6989 /* note: this check is placed so that if the caller passes
6990 * in a VARIANTARG for the retval we just ignore it, like
6992 if (i
== func_desc
->cParams
- 1)
6995 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6996 memset(arg
, 0, sizeof(*arg
));
6997 V_VT(arg
) = rgvt
[i
];
6998 memset(&retval
, 0, sizeof(retval
));
6999 V_BYREF(arg
) = &retval
;
7003 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7004 hres
= E_UNEXPECTED
;
7010 TRACE("%s\n", debugstr_variant(src_arg
));
7012 if(rgvt
[i
]!=V_VT(src_arg
))
7014 if (rgvt
[i
] == VT_VARIANT
)
7015 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7016 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7018 if (rgvt
[i
] == V_VT(src_arg
))
7019 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7022 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7023 if (wParamFlags
& PARAMFLAG_FIN
)
7024 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7025 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7027 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7029 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7032 SAFEARRAYBOUND bound
;
7036 bound
.cElements
= pDispParams
->cArgs
-i
;
7037 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7039 ERR("SafeArrayCreate failed\n");
7042 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7045 ERR("SafeArrayAccessData failed with %x\n", hres
);
7046 SafeArrayDestroy(a
);
7049 for (j
= 0; j
< bound
.cElements
; j
++)
7050 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7051 hres
= SafeArrayUnaccessData(a
);
7054 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7055 SafeArrayDestroy(a
);
7058 if (rgvt
[i
] & VT_BYREF
)
7059 V_BYREF(&rgvarg
[i
]) = &a
;
7061 V_ARRAY(&rgvarg
[i
]) = a
;
7062 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7064 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7066 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7067 if (wParamFlags
& PARAMFLAG_FIN
)
7068 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7070 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7071 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7072 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7074 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7076 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7077 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7081 /* FIXME: this doesn't work for VT_BYREF arguments if
7082 * they are not the same type as in the paramdesc */
7083 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7084 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7085 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7090 ERR("failed to convert param %d to %s from %s\n", i
,
7091 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7094 prgpvarg
[i
] = &rgvarg
[i
];
7098 prgpvarg
[i
] = src_arg
;
7101 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7102 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7103 && V_UNKNOWN(prgpvarg
[i
])) {
7104 IUnknown
*userdefined_iface
;
7107 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7111 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7113 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7117 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7118 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7121 else if (wParamFlags
& PARAMFLAG_FOPT
)
7124 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7125 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7127 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7133 VARIANTARG
*missing_arg
;
7134 /* if the function wants a pointer to a variant then
7135 * set that up, otherwise just pass the VT_ERROR in
7136 * the argument by value */
7137 if (rgvt
[i
] & VT_BYREF
)
7139 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7140 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7141 V_VARIANTREF(arg
) = missing_arg
;
7145 V_VT(missing_arg
) = VT_ERROR
;
7146 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7151 hres
= DISP_E_BADPARAMCOUNT
;
7155 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7157 /* VT_VOID is a special case for return types, so it is not
7158 * handled in the general function */
7159 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7160 V_VT(&varresult
) = VT_EMPTY
;
7163 V_VT(&varresult
) = 0;
7164 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7165 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7168 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7169 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7170 prgpvarg
, &varresult
);
7172 vargs_converted
= 0;
7174 for (i
= 0; i
< func_desc
->cParams
; i
++)
7176 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7177 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7179 if (wParamFlags
& PARAMFLAG_FLCID
)
7181 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7183 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7187 VariantInit(pVarResult
);
7188 /* deref return value */
7189 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7192 VARIANT_ClearInd(prgpvarg
[i
]);
7194 else if (vargs_converted
< pDispParams
->cArgs
)
7196 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7197 if (wParamFlags
& PARAMFLAG_FOUT
)
7199 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7201 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7205 ERR("failed to convert param %d to vt %d\n", i
,
7206 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7211 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7212 func_desc
->cParamsOpt
< 0 &&
7213 i
== func_desc
->cParams
-1)
7215 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7218 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7221 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7224 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7227 ERR("SafeArrayAccessData failed with %x\n", hres
);
7230 for (j
= 0; j
<= ubound
; j
++)
7231 VariantClear(&v
[j
]);
7232 hres
= SafeArrayUnaccessData(a
);
7235 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7239 VariantClear(&rgvarg
[i
]);
7242 else if (wParamFlags
& PARAMFLAG_FOPT
)
7244 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7245 VariantClear(&rgvarg
[i
]);
7248 VariantClear(&missing_arg
[i
]);
7251 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7253 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7254 hres
= DISP_E_EXCEPTION
;
7257 IErrorInfo
*pErrorInfo
;
7258 pExcepInfo
->scode
= V_ERROR(&varresult
);
7259 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7261 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7262 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7263 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7264 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7266 IErrorInfo_Release(pErrorInfo
);
7270 if (V_VT(&varresult
) != VT_ERROR
)
7272 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7276 VariantClear(pVarResult
);
7277 *pVarResult
= varresult
;
7280 VariantClear(&varresult
);
7283 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7284 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7285 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7286 (pDispParams
->cArgs
!= 0))
7288 if (V_VT(pVarResult
) == VT_DISPATCH
)
7290 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7291 /* Note: not VariantClear; we still need the dispatch
7292 * pointer to be valid */
7293 VariantInit(pVarResult
);
7294 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7295 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7296 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7297 IDispatch_Release(pDispatch
);
7301 VariantClear(pVarResult
);
7302 hres
= DISP_E_NOTACOLLECTION
;
7310 case FUNC_DISPATCH
: {
7313 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7314 if (SUCCEEDED(hres
)) {
7315 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7316 hres
= IDispatch_Invoke(
7317 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7318 pVarResult
,pExcepInfo
,pArgErr
7321 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7322 IDispatch_Release(disp
);
7324 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7328 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7333 TRACE("-- 0x%08x\n", hres
);
7336 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7339 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7340 if(FAILED(hres
)) return hres
;
7342 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7343 dump_VARDESC(var_desc
);
7344 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7348 /* not found, look for it in inherited interfaces */
7349 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7350 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7351 if(This
->impltypes
) {
7352 /* recursive search */
7354 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7355 if(SUCCEEDED(hres
)){
7356 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7357 ITypeInfo_Release(pTInfo
);
7360 WARN("Could not search inherited interface!\n");
7363 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7364 return DISP_E_MEMBERNOTFOUND
;
7367 /* ITypeInfo::GetDocumentation
7369 * Retrieves the documentation string, the complete Help file name and path,
7370 * and the context ID for the Help topic for a specified type description.
7372 * (Can be tested by the Visual Basic Editor in Word for instance.)
7374 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7375 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7376 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7378 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7379 const TLBFuncDesc
*pFDesc
;
7380 const TLBVarDesc
*pVDesc
;
7381 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7382 " HelpContext(%p) HelpFile(%p)\n",
7383 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7384 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7386 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7388 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7390 *pdwHelpContext
=This
->dwHelpContext
;
7392 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7394 }else {/* for a member */
7395 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7398 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7400 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7402 *pdwHelpContext
=pFDesc
->helpcontext
;
7404 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7407 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
7410 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7412 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7414 *pdwHelpContext
=pVDesc
->HelpContext
;
7416 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7421 if(This
->impltypes
&&
7422 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7423 /* recursive search */
7426 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7427 if(SUCCEEDED(result
)) {
7428 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7429 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7430 ITypeInfo_Release(pTInfo
);
7433 WARN("Could not search inherited interface!\n");
7436 WARN("member %d not found\n", memid
);
7437 return TYPE_E_ELEMENTNOTFOUND
;
7440 /* ITypeInfo::GetDllEntry
7442 * Retrieves a description or specification of an entry point for a function
7445 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7446 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7449 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7450 const TLBFuncDesc
*pFDesc
;
7452 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7454 if (pBstrDllName
) *pBstrDllName
= NULL
;
7455 if (pBstrName
) *pBstrName
= NULL
;
7456 if (pwOrdinal
) *pwOrdinal
= 0;
7458 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7459 return TYPE_E_BADMODULEKIND
;
7461 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7463 dump_TypeInfo(This
);
7465 dump_TLBFuncDescOne(pFDesc
);
7468 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7470 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7472 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7480 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7483 return TYPE_E_ELEMENTNOTFOUND
;
7486 /* internal function to make the inherited interfaces' methods appear
7487 * part of the interface */
7488 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7489 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7491 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7494 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7496 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7498 ITypeInfo
*pSubTypeInfo
;
7500 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7504 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7506 ITypeInfo_Release(pSubTypeInfo
);
7510 *hRefType
-= DISPATCH_HREF_OFFSET
;
7512 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7513 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7518 struct search_res_tlb_params
7524 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7526 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7527 static const WCHAR formatW
[] = {'\\','%','d',0};
7528 WCHAR szPath
[MAX_PATH
+1];
7529 ITypeLib
*pTLib
= NULL
;
7533 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7536 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7539 if (snprintfW(szPath
+ len
, sizeof(szPath
)/sizeof(WCHAR
) - len
, formatW
, LOWORD(lpszName
)) < 0)
7542 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7545 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7546 if (IsEqualGUID(params
->guid
, impl
->guid
))
7548 params
->pTLib
= pTLib
;
7549 return FALSE
; /* stop enumeration */
7551 ITypeLib_Release(pTLib
);
7557 /* ITypeInfo::GetRefTypeInfo
7559 * If a type description references other type descriptions, it retrieves
7560 * the referenced type descriptions.
7562 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7565 ITypeInfo
**ppTInfo
)
7567 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7568 HRESULT result
= E_FAIL
;
7571 return E_INVALIDARG
;
7573 if ((INT
)hRefType
< 0) {
7574 ITypeInfoImpl
*pTypeInfoImpl
;
7576 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7577 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7578 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7579 return TYPE_E_ELEMENTNOTFOUND
;
7581 /* when we meet a DUAL typeinfo, we must create the alternate
7584 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7586 *pTypeInfoImpl
= *This
;
7587 pTypeInfoImpl
->ref
= 0;
7588 list_init(&pTypeInfoImpl
->custdata_list
);
7590 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7591 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7593 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7595 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7596 /* the AddRef implicitly adds a reference to the parent typelib, which
7597 * stops the copied data from being destroyed until the new typeinfo's
7598 * refcount goes to zero, but we need to signal to the new instance to
7599 * not free its data structures when it is destroyed */
7600 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7602 ITypeInfo_AddRef(*ppTInfo
);
7605 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7606 (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7608 HREFTYPE href_dispatch
= hRefType
;
7609 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7611 TLBRefType
*ref_type
;
7612 ITypeLib
*pTLib
= NULL
;
7615 if(!(hRefType
& 0x1)){
7616 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7618 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7621 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7622 ITypeInfo_AddRef(*ppTInfo
);
7628 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7630 if(ref_type
->reference
== (hRefType
& (~0x3)))
7633 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7635 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7639 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7641 TRACE("internal reference\n");
7642 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7644 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7645 TRACE("typeinfo in imported typelib that is already loaded\n");
7646 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7647 ITypeLib_AddRef(pTLib
);
7650 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
7651 struct search_res_tlb_params params
;
7654 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7656 /* Search in resource table */
7657 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
7658 params
.pTLib
= NULL
;
7659 EnumResourceNamesW(NULL
, TYPELIBW
, search_res_tlb
, (LONG_PTR
)¶ms
);
7660 pTLib
= params
.pTLib
;
7665 /* Search on disk */
7666 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7667 ref_type
->pImpTLInfo
->wVersionMajor
,
7668 ref_type
->pImpTLInfo
->wVersionMinor
,
7669 This
->pTypeLib
->syskind
,
7670 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7672 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7674 result
= LoadTypeLib(libnam
, &pTLib
);
7675 SysFreeString(libnam
);
7678 if(SUCCEEDED(result
)) {
7679 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7680 ITypeLib_AddRef(pTLib
);
7684 if(SUCCEEDED(result
)) {
7685 if(ref_type
->index
== TLB_REF_USE_GUID
)
7686 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7688 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7691 ITypeLib_Release(pTLib
);
7695 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7696 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7700 /* ITypeInfo::AddressOfMember
7702 * Retrieves the addresses of static functions or variables, such as those
7705 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7706 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7708 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7714 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7716 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7720 module
= LoadLibraryW(dll
);
7723 ERR("couldn't load %s\n", debugstr_w(dll
));
7725 SysFreeString(entry
);
7726 return STG_E_FILENOTFOUND
;
7728 /* FIXME: store library somewhere where we can free it */
7733 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7734 entryA
= heap_alloc(len
);
7735 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7737 *ppv
= GetProcAddress(module
, entryA
);
7739 ERR("function not found %s\n", debugstr_a(entryA
));
7745 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7747 ERR("function not found %d\n", ordinal
);
7751 SysFreeString(entry
);
7754 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7759 /* ITypeInfo::CreateInstance
7761 * Creates a new instance of a type that describes a component object class
7764 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7765 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7767 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7771 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7777 WARN("Not able to aggregate\n");
7778 return CLASS_E_NOAGGREGATION
;
7781 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7782 if(FAILED(hr
)) return hr
;
7784 if(pTA
->typekind
!= TKIND_COCLASS
)
7786 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7792 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7795 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7796 TRACE("GetActiveObject rets %08x\n", hr
);
7799 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7800 IUnknown_Release(pUnk
);
7805 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7806 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7810 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7814 /* ITypeInfo::GetMops
7816 * Retrieves marshalling information.
7818 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7821 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7822 FIXME("(%p %d) stub!\n", This
, memid
);
7827 /* ITypeInfo::GetContainingTypeLib
7829 * Retrieves the containing type library and the index of the type description
7830 * within that type library.
7832 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7833 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7835 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7837 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7839 *pIndex
=This
->index
;
7840 TRACE("returning pIndex=%d\n", *pIndex
);
7844 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
7845 ITypeLib_AddRef(*ppTLib
);
7846 TRACE("returning ppTLib=%p\n", *ppTLib
);
7852 /* ITypeInfo::ReleaseTypeAttr
7854 * Releases a TYPEATTR previously returned by Get
7857 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7858 TYPEATTR
* pTypeAttr
)
7860 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7861 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7862 heap_free(pTypeAttr
);
7865 /* ITypeInfo::ReleaseFuncDesc
7867 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7869 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7871 FUNCDESC
*pFuncDesc
)
7873 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7876 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7878 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7879 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7880 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7882 SysFreeString((BSTR
)pFuncDesc
);
7885 /* ITypeInfo::ReleaseVarDesc
7887 * Releases a VARDESC previously returned by GetVarDesc.
7889 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7892 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7893 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7895 TLB_FreeVarDesc(pVarDesc
);
7898 /* ITypeInfo2::GetTypeKind
7900 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7903 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7904 TYPEKIND
*pTypeKind
)
7906 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7907 *pTypeKind
= This
->typeattr
.typekind
;
7908 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7912 /* ITypeInfo2::GetTypeFlags
7914 * Returns the type flags without any allocations. This returns a DWORD type
7915 * flag, which expands the type flags without growing the TYPEATTR (type
7919 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7921 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7922 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
7923 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7927 /* ITypeInfo2::GetFuncIndexOfMemId
7928 * Binds to a specific member based on a known DISPID, where the member name
7929 * is not known (for example, when binding to a default member).
7932 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7933 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7935 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7939 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7940 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7941 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7944 if(fdc
< This
->typeattr
.cFuncs
) {
7948 result
= TYPE_E_ELEMENTNOTFOUND
;
7950 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7951 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7955 /* TypeInfo2::GetVarIndexOfMemId
7957 * Binds to a specific member based on a known DISPID, where the member name
7958 * is not known (for example, when binding to a default member).
7961 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7962 MEMBERID memid
, UINT
*pVarIndex
)
7964 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7965 TLBVarDesc
*pVarInfo
;
7967 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7969 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
7971 return TYPE_E_ELEMENTNOTFOUND
;
7973 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7978 /* ITypeInfo2::GetCustData
7980 * Gets the custom data
7982 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7987 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7988 TLBCustData
*pCData
;
7990 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7992 if(!guid
|| !pVarVal
)
7993 return E_INVALIDARG
;
7995 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
7997 VariantInit( pVarVal
);
7999 VariantCopy( pVarVal
, &pCData
->data
);
8001 VariantClear( pVarVal
);
8005 /* ITypeInfo2::GetFuncCustData
8007 * Gets the custom data
8009 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8015 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8016 TLBCustData
*pCData
;
8017 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8019 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8021 if(index
>= This
->typeattr
.cFuncs
)
8022 return TYPE_E_ELEMENTNOTFOUND
;
8024 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8026 return TYPE_E_ELEMENTNOTFOUND
;
8028 VariantInit(pVarVal
);
8029 VariantCopy(pVarVal
, &pCData
->data
);
8034 /* ITypeInfo2::GetParamCustData
8036 * Gets the custom data
8038 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8045 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8046 TLBCustData
*pCData
;
8047 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8049 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8050 debugstr_guid(guid
), pVarVal
);
8052 if(indexFunc
>= This
->typeattr
.cFuncs
)
8053 return TYPE_E_ELEMENTNOTFOUND
;
8055 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8056 return TYPE_E_ELEMENTNOTFOUND
;
8058 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8060 return TYPE_E_ELEMENTNOTFOUND
;
8062 VariantInit(pVarVal
);
8063 VariantCopy(pVarVal
, &pCData
->data
);
8068 /* ITypeInfo2::GetVarCustData
8070 * Gets the custom data
8072 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8078 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8079 TLBCustData
*pCData
;
8080 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8082 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8084 if(index
>= This
->typeattr
.cVars
)
8085 return TYPE_E_ELEMENTNOTFOUND
;
8087 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8089 return TYPE_E_ELEMENTNOTFOUND
;
8091 VariantInit(pVarVal
);
8092 VariantCopy(pVarVal
, &pCData
->data
);
8097 /* ITypeInfo2::GetImplCustData
8099 * Gets the custom data
8101 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8107 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8108 TLBCustData
*pCData
;
8109 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8111 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8113 if(index
>= This
->typeattr
.cImplTypes
)
8114 return TYPE_E_ELEMENTNOTFOUND
;
8116 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8118 return TYPE_E_ELEMENTNOTFOUND
;
8120 VariantInit(pVarVal
);
8121 VariantCopy(pVarVal
, &pCData
->data
);
8126 /* ITypeInfo2::GetDocumentation2
8128 * Retrieves the documentation string, the complete Help file name and path,
8129 * the localization context to use, and the context ID for the library Help
8130 * topic in the Help file.
8133 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8137 BSTR
*pbstrHelpString
,
8138 DWORD
*pdwHelpStringContext
,
8139 BSTR
*pbstrHelpStringDll
)
8141 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8142 const TLBFuncDesc
*pFDesc
;
8143 const TLBVarDesc
*pVDesc
;
8144 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8145 "HelpStringContext(%p) HelpStringDll(%p)\n",
8146 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8147 pbstrHelpStringDll
);
8148 /* the help string should be obtained from the helpstringdll,
8149 * using the _DLLGetDocumentation function, based on the supplied
8150 * lcid. Nice to do sometime...
8152 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8154 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8155 if(pdwHelpStringContext
)
8156 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8157 if(pbstrHelpStringDll
)
8158 *pbstrHelpStringDll
=
8159 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8161 }else {/* for a member */
8162 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
8165 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8166 if(pdwHelpStringContext
)
8167 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8168 if(pbstrHelpStringDll
)
8169 *pbstrHelpStringDll
=
8170 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8173 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
8176 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8177 if(pdwHelpStringContext
)
8178 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8179 if(pbstrHelpStringDll
)
8180 *pbstrHelpStringDll
=
8181 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8185 return TYPE_E_ELEMENTNOTFOUND
;
8188 /* ITypeInfo2::GetAllCustData
8190 * Gets all custom data items for the Type info.
8193 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8195 CUSTDATA
*pCustData
)
8197 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8199 TRACE("%p %p\n", This
, pCustData
);
8201 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8204 /* ITypeInfo2::GetAllFuncCustData
8206 * Gets all custom data items for the specified Function
8209 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8212 CUSTDATA
*pCustData
)
8214 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8215 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8217 TRACE("%p %u %p\n", This
, index
, pCustData
);
8219 if(index
>= This
->typeattr
.cFuncs
)
8220 return TYPE_E_ELEMENTNOTFOUND
;
8222 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8225 /* ITypeInfo2::GetAllParamCustData
8227 * Gets all custom data items for the Functions
8230 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8231 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8233 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8234 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8236 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8238 if(indexFunc
>= This
->typeattr
.cFuncs
)
8239 return TYPE_E_ELEMENTNOTFOUND
;
8241 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8242 return TYPE_E_ELEMENTNOTFOUND
;
8244 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8247 /* ITypeInfo2::GetAllVarCustData
8249 * Gets all custom data items for the specified Variable
8252 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8253 UINT index
, CUSTDATA
*pCustData
)
8255 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8256 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8258 TRACE("%p %u %p\n", This
, index
, pCustData
);
8260 if(index
>= This
->typeattr
.cVars
)
8261 return TYPE_E_ELEMENTNOTFOUND
;
8263 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8266 /* ITypeInfo2::GetAllImplCustData
8268 * Gets all custom data items for the specified implementation type
8271 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8274 CUSTDATA
*pCustData
)
8276 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8277 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8279 TRACE("%p %u %p\n", This
, index
, pCustData
);
8281 if(index
>= This
->typeattr
.cImplTypes
)
8282 return TYPE_E_ELEMENTNOTFOUND
;
8284 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8287 static const ITypeInfo2Vtbl tinfvt
=
8290 ITypeInfo_fnQueryInterface
,
8292 ITypeInfo_fnRelease
,
8294 ITypeInfo_fnGetTypeAttr
,
8295 ITypeInfo_fnGetTypeComp
,
8296 ITypeInfo_fnGetFuncDesc
,
8297 ITypeInfo_fnGetVarDesc
,
8298 ITypeInfo_fnGetNames
,
8299 ITypeInfo_fnGetRefTypeOfImplType
,
8300 ITypeInfo_fnGetImplTypeFlags
,
8301 ITypeInfo_fnGetIDsOfNames
,
8303 ITypeInfo_fnGetDocumentation
,
8304 ITypeInfo_fnGetDllEntry
,
8305 ITypeInfo_fnGetRefTypeInfo
,
8306 ITypeInfo_fnAddressOfMember
,
8307 ITypeInfo_fnCreateInstance
,
8308 ITypeInfo_fnGetMops
,
8309 ITypeInfo_fnGetContainingTypeLib
,
8310 ITypeInfo_fnReleaseTypeAttr
,
8311 ITypeInfo_fnReleaseFuncDesc
,
8312 ITypeInfo_fnReleaseVarDesc
,
8314 ITypeInfo2_fnGetTypeKind
,
8315 ITypeInfo2_fnGetTypeFlags
,
8316 ITypeInfo2_fnGetFuncIndexOfMemId
,
8317 ITypeInfo2_fnGetVarIndexOfMemId
,
8318 ITypeInfo2_fnGetCustData
,
8319 ITypeInfo2_fnGetFuncCustData
,
8320 ITypeInfo2_fnGetParamCustData
,
8321 ITypeInfo2_fnGetVarCustData
,
8322 ITypeInfo2_fnGetImplTypeCustData
,
8323 ITypeInfo2_fnGetDocumentation2
,
8324 ITypeInfo2_fnGetAllCustData
,
8325 ITypeInfo2_fnGetAllFuncCustData
,
8326 ITypeInfo2_fnGetAllParamCustData
,
8327 ITypeInfo2_fnGetAllVarCustData
,
8328 ITypeInfo2_fnGetAllImplTypeCustData
,
8331 /******************************************************************************
8332 * CreateDispTypeInfo [OLEAUT32.31]
8334 * Build type information for an object so it can be called through an
8335 * IDispatch interface.
8338 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8339 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8342 * This call allows an objects methods to be accessed through IDispatch, by
8343 * building an ITypeInfo object that IDispatch can use to call through.
8345 HRESULT WINAPI
CreateDispTypeInfo(
8346 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8347 LCID lcid
, /* [I] Locale Id */
8348 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8350 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8351 ITypeLibImpl
*pTypeLibImpl
;
8352 unsigned int param
, func
;
8353 TLBFuncDesc
*pFuncDesc
;
8357 pTypeLibImpl
= TypeLibImpl_Constructor();
8358 if (!pTypeLibImpl
) return E_FAIL
;
8360 pTypeLibImpl
->TypeInfoCount
= 2;
8361 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8363 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8364 pTIIface
->pTypeLib
= pTypeLibImpl
;
8365 pTIIface
->index
= 0;
8366 pTIIface
->Name
= NULL
;
8367 pTIIface
->dwHelpContext
= -1;
8368 pTIIface
->guid
= NULL
;
8369 pTIIface
->typeattr
.lcid
= lcid
;
8370 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8371 pTIIface
->typeattr
.wMajorVerNum
= 0;
8372 pTIIface
->typeattr
.wMinorVerNum
= 0;
8373 pTIIface
->typeattr
.cbAlignment
= 2;
8374 pTIIface
->typeattr
.cbSizeInstance
= -1;
8375 pTIIface
->typeattr
.cbSizeVft
= -1;
8376 pTIIface
->typeattr
.cFuncs
= 0;
8377 pTIIface
->typeattr
.cImplTypes
= 0;
8378 pTIIface
->typeattr
.cVars
= 0;
8379 pTIIface
->typeattr
.wTypeFlags
= 0;
8380 pTIIface
->hreftype
= 0;
8382 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8383 pFuncDesc
= pTIIface
->funcdescs
;
8384 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8385 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8386 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8387 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8388 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8389 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8390 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8391 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8392 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8393 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8394 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8395 pFuncDesc
->funcdesc
.cScodes
= 0;
8396 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8397 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8398 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8399 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8400 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8401 md
->cArgs
* sizeof(ELEMDESC
));
8402 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8403 for(param
= 0; param
< md
->cArgs
; param
++) {
8404 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8405 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8407 pFuncDesc
->helpcontext
= 0;
8408 pFuncDesc
->HelpStringContext
= 0;
8409 pFuncDesc
->HelpString
= NULL
;
8410 pFuncDesc
->Entry
= NULL
;
8411 list_init(&pFuncDesc
->custdata_list
);
8412 pTIIface
->typeattr
.cFuncs
++;
8416 dump_TypeInfo(pTIIface
);
8418 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8419 pTIClass
->pTypeLib
= pTypeLibImpl
;
8420 pTIClass
->index
= 1;
8421 pTIClass
->Name
= NULL
;
8422 pTIClass
->dwHelpContext
= -1;
8423 pTIClass
->guid
= NULL
;
8424 pTIClass
->typeattr
.lcid
= lcid
;
8425 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8426 pTIClass
->typeattr
.wMajorVerNum
= 0;
8427 pTIClass
->typeattr
.wMinorVerNum
= 0;
8428 pTIClass
->typeattr
.cbAlignment
= 2;
8429 pTIClass
->typeattr
.cbSizeInstance
= -1;
8430 pTIClass
->typeattr
.cbSizeVft
= -1;
8431 pTIClass
->typeattr
.cFuncs
= 0;
8432 pTIClass
->typeattr
.cImplTypes
= 1;
8433 pTIClass
->typeattr
.cVars
= 0;
8434 pTIClass
->typeattr
.wTypeFlags
= 0;
8435 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8437 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8439 ref
= heap_alloc_zero(sizeof(*ref
));
8440 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8441 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8443 dump_TypeInfo(pTIClass
);
8445 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8447 ITypeInfo_AddRef(*pptinfo
);
8448 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8454 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8456 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8458 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8461 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8463 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8465 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8468 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8470 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8472 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8475 static HRESULT WINAPI
ITypeComp_fnBind(
8480 ITypeInfo
** ppTInfo
,
8481 DESCKIND
* pDescKind
,
8484 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8485 const TLBFuncDesc
*pFDesc
;
8486 const TLBVarDesc
*pVDesc
;
8487 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8490 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8492 *pDescKind
= DESCKIND_NONE
;
8493 pBindPtr
->lpfuncdesc
= NULL
;
8496 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8497 pFDesc
= &This
->funcdescs
[fdc
];
8498 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8499 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8502 /* name found, but wrong flags */
8503 hr
= TYPE_E_TYPEMISMATCH
;
8507 if (fdc
< This
->typeattr
.cFuncs
)
8509 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8511 &pBindPtr
->lpfuncdesc
,
8512 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8515 *pDescKind
= DESCKIND_FUNCDESC
;
8516 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8517 ITypeInfo_AddRef(*ppTInfo
);
8520 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, szName
);
8522 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8525 *pDescKind
= DESCKIND_VARDESC
;
8526 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8527 ITypeInfo_AddRef(*ppTInfo
);
8532 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8533 /* recursive search */
8537 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8540 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8541 ITypeInfo_Release(pTInfo
);
8545 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8546 ITypeComp_Release(pTComp
);
8547 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8548 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8550 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8551 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8552 SysFreeString((BSTR
)tmp
);
8556 WARN("Could not search inherited interface!\n");
8558 if (hr
== DISP_E_MEMBERNOTFOUND
)
8560 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8564 static HRESULT WINAPI
ITypeComp_fnBindType(
8568 ITypeInfo
** ppTInfo
,
8569 ITypeComp
** ppTComp
)
8571 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8573 /* strange behaviour (does nothing) but like the
8576 if (!ppTInfo
|| !ppTComp
)
8585 static const ITypeCompVtbl tcompvt
=
8588 ITypeComp_fnQueryInterface
,
8590 ITypeComp_fnRelease
,
8593 ITypeComp_fnBindType
8596 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8597 ICreateTypeLib2
** ppctlib
)
8602 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8604 if (!szFile
) return E_INVALIDARG
;
8606 This
= TypeLibImpl_Constructor();
8608 return E_OUTOFMEMORY
;
8610 This
->lcid
= GetSystemDefaultLCID();
8611 This
->syskind
= syskind
;
8612 This
->ptr_size
= get_ptr_size(syskind
);
8614 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8616 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8617 return E_OUTOFMEMORY
;
8619 lstrcpyW(This
->path
, szFile
);
8621 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8622 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8626 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8627 REFIID riid
, void **object
)
8629 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8631 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8634 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8636 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8638 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8641 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8643 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8645 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8648 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8649 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8651 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8652 ITypeInfoImpl
*info
;
8655 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8657 if (!ctinfo
|| !name
)
8658 return E_INVALIDARG
;
8660 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8662 return TYPE_E_NAMECONFLICT
;
8664 if (This
->typeinfos
)
8665 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8666 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8668 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8670 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8672 info
->pTypeLib
= This
;
8673 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8674 info
->index
= This
->TypeInfoCount
;
8675 info
->typeattr
.typekind
= kind
;
8676 info
->typeattr
.cbAlignment
= 4;
8678 switch (info
->typeattr
.typekind
) {
8680 case TKIND_INTERFACE
:
8681 case TKIND_DISPATCH
:
8683 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
8687 info
->typeattr
.cbSizeInstance
= 0;
8690 info
->typeattr
.cbSizeInstance
= 2;
8693 info
->typeattr
.cbSizeInstance
= -0x75;
8696 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
8697 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
8701 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8702 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8704 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8708 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8710 ++This
->TypeInfoCount
;
8715 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8718 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8720 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8723 return E_INVALIDARG
;
8725 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8730 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8731 WORD majorVerNum
, WORD minorVerNum
)
8733 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8735 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8737 This
->ver_major
= majorVerNum
;
8738 This
->ver_minor
= minorVerNum
;
8743 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8746 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8748 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8750 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8755 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8758 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8760 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8763 return E_INVALIDARG
;
8765 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8770 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8771 LPOLESTR helpFileName
)
8773 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8775 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8778 return E_INVALIDARG
;
8780 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8785 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8788 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8790 TRACE("%p %d\n", This
, helpContext
);
8792 This
->dwHelpContext
= helpContext
;
8797 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8800 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8802 TRACE("%p %x\n", This
, lcid
);
8804 This
->set_lcid
= lcid
;
8809 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8812 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8814 TRACE("%p %x\n", This
, libFlags
);
8816 This
->libflags
= libFlags
;
8821 typedef struct tagWMSFT_SegContents
{
8824 } WMSFT_SegContents
;
8826 typedef struct tagWMSFT_TLBFile
{
8828 WMSFT_SegContents typeinfo_seg
;
8829 WMSFT_SegContents impfile_seg
;
8830 WMSFT_SegContents impinfo_seg
;
8831 WMSFT_SegContents ref_seg
;
8832 WMSFT_SegContents guidhash_seg
;
8833 WMSFT_SegContents guid_seg
;
8834 WMSFT_SegContents namehash_seg
;
8835 WMSFT_SegContents name_seg
;
8836 WMSFT_SegContents string_seg
;
8837 WMSFT_SegContents typdesc_seg
;
8838 WMSFT_SegContents arraydesc_seg
;
8839 WMSFT_SegContents custdata_seg
;
8840 WMSFT_SegContents cdguids_seg
;
8842 WMSFT_SegContents aux_seg
;
8845 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8846 WMSFT_TLBFile
*file
)
8852 file
->string_seg
.len
= 0;
8853 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8856 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8858 return E_UNEXPECTED
;
8860 size
+= sizeof(INT16
);
8862 size
= (size
+ 4) & ~0x3;
8866 file
->string_seg
.len
+= size
;
8868 /* temporarily use str->offset to store the length of the aligned,
8869 * converted string */
8873 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8876 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8879 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8880 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8882 heap_free(file
->string_seg
.data
);
8883 return E_UNEXPECTED
;
8886 *((INT16
*)data
) = size
;
8888 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8892 str
->offset
= last_offs
;
8899 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8900 WMSFT_TLBFile
*file
)
8905 MSFT_NameIntro
*last_intro
= NULL
;
8907 file
->header
.nametablecount
= 0;
8908 file
->header
.nametablechars
= 0;
8910 file
->name_seg
.len
= 0;
8911 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8914 size
= strlenW(str
->str
);
8915 file
->header
.nametablechars
+= size
;
8916 file
->header
.nametablecount
++;
8918 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8920 return E_UNEXPECTED
;
8922 size
+= sizeof(MSFT_NameIntro
);
8924 size
= (size
+ 4) & ~0x3;
8928 file
->name_seg
.len
+= size
;
8930 /* temporarily use str->offset to store the length of the aligned,
8931 * converted string */
8935 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8936 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
8939 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8941 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8943 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8944 data
+ sizeof(MSFT_NameIntro
),
8945 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8947 heap_free(file
->name_seg
.data
);
8948 return E_UNEXPECTED
;
8950 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
8952 intro
->hreftype
= -1; /* TODO? */
8953 intro
->namelen
= size
& 0xFF;
8954 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8955 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
8956 intro
->namelen
|= hash
<< 16;
8957 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
8958 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
8960 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
8961 str
->offset
- size
- sizeof(MSFT_NameIntro
));
8963 /* update str->offset to actual value to use in other
8964 * compilation functions that require positions within
8965 * the string table */
8969 str
->offset
= last_offs
;
8974 last_intro
->hreftype
= 0; /* last one is 0? */
8979 static inline int hash_guid(GUID
*guid
)
8983 for (i
= 0; i
< 8; i
++)
8984 hash
^= ((const short *)guid
)[i
];
8989 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
8992 MSFT_GuidEntry
*entry
;
8994 int hash_key
, *guidhashtab
;
8996 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
8997 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
8999 entry
= file
->guid_seg
.data
;
9001 guidhashtab
= file
->guidhash_seg
.data
;
9002 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9003 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9004 entry
->hreftype
= guid
->hreftype
;
9006 hash_key
= hash_guid(&guid
->guid
);
9007 entry
->next_hash
= guidhashtab
[hash_key
];
9008 guidhashtab
[hash_key
] = offs
;
9010 guid
->offset
= offs
;
9011 offs
+= sizeof(MSFT_GuidEntry
);
9018 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9021 VARTYPE arg_type
= V_VT(value
);
9024 DWORD ret
= file
->custdata_seg
.len
;
9026 if(arg_type
== VT_INT
)
9028 if(arg_type
== VT_UINT
)
9032 if(V_VT(value
) != arg_type
) {
9033 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9035 ERR("VariantChangeType failed: %08x\n", hres
);
9040 /* Check if default value can be stored in-place */
9045 if(V_UI4(&v
) > 0x3ffffff)
9058 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9061 /* have to allocate space in custdata_seg */
9070 /* Construct the data to be allocated */
9073 if(file
->custdata_seg
.data
){
9074 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9075 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9076 file
->custdata_seg
.len
+= sizeof(int) * 2;
9078 file
->custdata_seg
.len
= sizeof(int) * 2;
9079 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9082 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9083 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9085 /* TODO: Check if the encoded data is already present in custdata_seg */
9091 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9094 if(file
->custdata_seg
.data
){
9095 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9096 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9097 file
->custdata_seg
.len
+= len
;
9099 file
->custdata_seg
.len
= len
;
9100 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9103 *((unsigned short *)data
) = V_VT(value
);
9104 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9105 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9106 if(V_BSTR(&v
)[i
] <= 0x7f)
9107 data
[i
+6] = V_BSTR(&v
)[i
];
9111 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9112 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9115 /* TODO: Check if the encoded data is already present in custdata_seg */
9120 FIXME("Argument type not yet handled\n");
9125 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9127 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9129 DWORD offs
= file
->arraydesc_seg
.len
;
9133 /* TODO: we should check for duplicates, but that's harder because each
9134 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9135 * at the library-level) */
9137 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9138 if(!file
->arraydesc_seg
.data
)
9139 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9141 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9142 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9144 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9145 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9146 for(i
= 0; i
< desc
->cDims
; ++i
){
9147 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9148 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9154 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9160 VARTYPE vt
, subtype
;
9171 vt
= desc
->vt
& VT_TYPEMASK
;
9173 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9175 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9176 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9178 *out_size
+= 2 * sizeof(DWORD
);
9179 }else if(vt
== VT_CARRAY
){
9180 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9181 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9183 }else if(vt
== VT_USERDEFINED
){
9184 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9185 encoded
[1] = desc
->u
.hreftype
;
9186 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9188 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9206 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9209 data
= file
->typdesc_seg
.data
;
9210 while(offs
< file
->typdesc_seg
.len
){
9211 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9213 offs
+= sizeof(encoded
);
9216 file
->typdesc_seg
.len
+= sizeof(encoded
);
9217 if(!file
->typdesc_seg
.data
)
9218 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9220 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9222 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9227 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9229 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9230 DWORD ret
= cdguids_seg
->len
, offs
;
9231 MSFT_CDGuid
*cdguid
;
9234 if(list_empty(custdata_list
))
9237 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9238 if(!cdguids_seg
->data
){
9239 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9241 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9242 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9245 offs
= ret
+ sizeof(MSFT_CDGuid
);
9246 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9247 cdguid
->GuidOffset
= cd
->guid
->offset
;
9248 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9249 cdguid
->next
= offs
;
9250 offs
+= sizeof(MSFT_CDGuid
);
9260 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9261 WMSFT_TLBFile
*file
)
9263 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9264 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9265 MSFT_VarRecord
*varrecord
;
9266 MSFT_FuncRecord
*funcrecord
;
9268 DWORD
*name
, *offsets
, offs
;
9270 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9271 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9273 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9275 /* optional fields */
9276 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9277 if(!list_empty(&desc
->custdata_list
))
9278 recorded_size
+= 7 * sizeof(INT
);
9279 else if(desc
->HelpStringContext
!= 0)
9280 recorded_size
+= 6 * sizeof(INT
);
9282 else if(desc
->Entry
)
9283 recorded_size
+= 3 * sizeof(INT
);
9284 else if(desc
->HelpString
)
9285 recorded_size
+= 2 * sizeof(INT
);
9286 else if(desc
->helpcontext
)
9287 recorded_size
+= sizeof(INT
);
9289 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9291 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9292 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9293 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9298 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9301 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9302 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9304 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9306 /* optional fields */
9307 if(desc
->HelpStringContext
!= 0)
9308 recorded_size
+= 5 * sizeof(INT
);
9309 else if(!list_empty(&desc
->custdata_list
))
9310 recorded_size
+= 4 * sizeof(INT
);
9312 else if(desc
->HelpString
)
9313 recorded_size
+= 2 * sizeof(INT
);
9314 else if(desc
->HelpContext
!= 0)
9315 recorded_size
+= sizeof(INT
);
9317 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9320 if(!recorded_size
&& !extra_size
)
9323 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9325 aux_seg
->len
+= recorded_size
+ extra_size
;
9327 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9330 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9332 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9334 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9336 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9339 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9340 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9341 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9342 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9344 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9345 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9346 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9347 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9350 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9355 * ^has_param_defaults
9356 * ^oEntry_is_intresource
9358 funcrecord
->FKCCIC
=
9359 desc
->funcdesc
.funckind
|
9360 (desc
->funcdesc
.invkind
<< 3) |
9361 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9362 (desc
->funcdesc
.callconv
<< 8);
9364 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9365 funcrecord
->FKCCIC
|= 0x2000;
9367 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9368 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9369 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9370 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9373 if(paramdefault_size
> 0)
9374 funcrecord
->FKCCIC
|= 0x1000;
9376 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9377 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9379 /* optional fields */
9381 if(!list_empty(&desc
->custdata_list
)){
9382 size
+= 7 * sizeof(INT
);
9383 funcrecord
->HelpContext
= desc
->helpcontext
;
9384 if(desc
->HelpString
)
9385 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9387 funcrecord
->oHelpString
= -1;
9389 funcrecord
->oEntry
= -1;
9390 else if(IS_INTRESOURCE(desc
->Entry
))
9391 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9393 funcrecord
->oEntry
= desc
->Entry
->offset
;
9394 funcrecord
->res9
= -1;
9395 funcrecord
->resA
= -1;
9396 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9397 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9398 }else if(desc
->HelpStringContext
!= 0){
9399 size
+= 6 * sizeof(INT
);
9400 funcrecord
->HelpContext
= desc
->helpcontext
;
9401 if(desc
->HelpString
)
9402 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9404 funcrecord
->oHelpString
= -1;
9406 funcrecord
->oEntry
= -1;
9407 else if(IS_INTRESOURCE(desc
->Entry
))
9408 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9410 funcrecord
->oEntry
= desc
->Entry
->offset
;
9411 funcrecord
->res9
= -1;
9412 funcrecord
->resA
= -1;
9413 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9414 }else if(desc
->Entry
){
9415 size
+= 3 * sizeof(INT
);
9416 funcrecord
->HelpContext
= desc
->helpcontext
;
9417 if(desc
->HelpString
)
9418 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9420 funcrecord
->oHelpString
= -1;
9422 funcrecord
->oEntry
= -1;
9423 else if(IS_INTRESOURCE(desc
->Entry
))
9424 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9426 funcrecord
->oEntry
= desc
->Entry
->offset
;
9427 }else if(desc
->HelpString
){
9428 size
+= 2 * sizeof(INT
);
9429 funcrecord
->HelpContext
= desc
->helpcontext
;
9430 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9431 }else if(desc
->helpcontext
){
9432 size
+= sizeof(INT
);
9433 funcrecord
->HelpContext
= desc
->helpcontext
;
9436 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9437 size
+= paramdefault_size
;
9439 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9440 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9442 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9443 if(desc
->pParamDesc
[j
].Name
)
9444 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9447 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9449 if(paramdefault_size
){
9450 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9451 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9452 else if(paramdefault_size
)
9457 size
+= sizeof(MSFT_ParameterInfo
);
9460 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9466 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9469 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9470 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9471 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9472 DWORD size
= 5 * sizeof(INT
);
9474 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9475 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9476 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9477 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9479 if(desc
->vardesc
.varkind
== VAR_CONST
){
9480 varrecord
->vardescsize
+= sizeof(VARIANT
);
9481 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9483 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9486 if(desc
->HelpStringContext
!= 0){
9487 size
+= 5 * sizeof(INT
);
9488 varrecord
->HelpContext
= desc
->HelpContext
;
9489 if(desc
->HelpString
)
9490 varrecord
->HelpString
= desc
->HelpString
->offset
;
9492 varrecord
->HelpString
= -1;
9493 varrecord
->res9
= -1;
9494 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9495 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9496 }else if(!list_empty(&desc
->custdata_list
)){
9497 size
+= 4 * sizeof(INT
);
9498 varrecord
->HelpContext
= desc
->HelpContext
;
9499 if(desc
->HelpString
)
9500 varrecord
->HelpString
= desc
->HelpString
->offset
;
9502 varrecord
->HelpString
= -1;
9503 varrecord
->res9
= -1;
9504 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9505 }else if(desc
->HelpString
){
9506 size
+= 2 * sizeof(INT
);
9507 varrecord
->HelpContext
= desc
->HelpContext
;
9508 if(desc
->HelpString
)
9509 varrecord
->HelpString
= desc
->HelpString
->offset
;
9511 varrecord
->HelpString
= -1;
9512 }else if(desc
->HelpContext
!= 0){
9513 size
+= sizeof(INT
);
9514 varrecord
->HelpContext
= desc
->HelpContext
;
9517 varrecord
->Info
= size
| (i
<< 16);
9523 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9526 memid
= (MEMBERID
*)varrecord
;
9527 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9528 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9529 *memid
= desc
->funcdesc
.memid
;
9532 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9533 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9534 *memid
= desc
->vardesc
.memid
;
9538 name
= (UINT
*)memid
;
9539 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9540 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9542 *name
= desc
->Name
->offset
;
9547 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9548 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9550 *name
= desc
->Name
->offset
;
9559 typedef struct tagWMSFT_RefChunk
{
9566 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9568 DWORD offs
= file
->ref_seg
.len
, i
;
9569 WMSFT_RefChunk
*chunk
;
9571 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9572 if(!file
->ref_seg
.data
)
9573 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9575 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9577 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9579 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9580 chunk
->href
= info
->impltypes
[i
].hRef
;
9581 chunk
->res04
= info
->impltypes
[i
].implflags
;
9583 if(i
< info
->typeattr
.cImplTypes
- 1)
9584 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9593 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9597 size
= sizeof(MSFT_TypeInfoBase
);
9600 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9601 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9602 base
->typekind
= TKIND_DISPATCH
;
9604 base
->typekind
= info
->typeattr
.typekind
;
9605 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9606 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
9607 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9612 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
9618 base
->posguid
= info
->guid
->offset
;
9621 base
->flags
= info
->typeattr
.wTypeFlags
;
9623 base
->NameOffset
= info
->Name
->offset
;
9625 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9626 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9628 base
->NameOffset
= -1;
9630 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
9632 base
->docstringoffs
= info
->DocString
->offset
;
9634 base
->docstringoffs
= -1;
9635 base
->helpstringcontext
= info
->dwHelpStringContext
;
9636 base
->helpcontext
= info
->dwHelpContext
;
9637 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9638 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
9639 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
9640 base
->size
= info
->typeattr
.cbSizeInstance
;
9641 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
9642 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9643 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
9644 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9645 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
9647 base
->datatype1
= info
->DllName
->offset
;
9649 base
->datatype1
= -1;
9651 if(info
->typeattr
.cImplTypes
> 0)
9652 base
->datatype1
= info
->impltypes
[0].hRef
;
9654 base
->datatype1
= -1;
9656 base
->datatype2
= index
; /* FIXME: i think there's more here */
9664 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9668 file
->typeinfo_seg
.len
= 0;
9669 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9670 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9671 *junk
= file
->typeinfo_seg
.len
;
9673 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9676 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9677 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9679 file
->aux_seg
.len
= 0;
9680 file
->aux_seg
.data
= NULL
;
9682 file
->typeinfo_seg
.len
= 0;
9683 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9684 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9685 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9686 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9690 typedef struct tagWMSFT_ImpFile
{
9696 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9699 WMSFT_ImpFile
*impfile
;
9701 DWORD last_offs
= 0;
9703 file
->impfile_seg
.len
= 0;
9704 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9708 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9712 path
= implib
->name
;
9713 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9715 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9718 size
+= sizeof(INT16
);
9720 size
= (size
+ 4) & ~0x3;
9724 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9727 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9729 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9730 int strlen
= 0, size
;
9732 impfile
= (WMSFT_ImpFile
*)data
;
9733 impfile
->guid_offs
= implib
->guid
->offset
;
9734 impfile
->lcid
= implib
->lcid
;
9735 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9737 data
+= sizeof(WMSFT_ImpFile
);
9740 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9744 path
= implib
->name
;
9745 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9746 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9748 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9751 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9753 size
= strlen
+ sizeof(INT16
);
9755 size
= (size
+ 4) & ~0x3;
9758 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9761 implib
->offset
= last_offs
;
9762 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9766 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9769 TLBRefType
*ref_type
;
9772 WMSFT_compile_impfile(This
, file
);
9774 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9775 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9777 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9778 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9779 if(ref_type
->index
== TLB_REF_USE_GUID
){
9780 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9781 info
->oGuid
= ref_type
->guid
->offset
;
9783 info
->oGuid
= ref_type
->index
;
9784 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9790 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9792 file
->guidhash_seg
.len
= 0x80;
9793 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9794 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9797 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9799 file
->namehash_seg
.len
= 0x200;
9800 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9801 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9804 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9806 if(contents
&& contents
->len
){
9807 segdir
->offset
= *running_offset
;
9808 segdir
->length
= contents
->len
;
9809 *running_offset
+= segdir
->length
;
9811 segdir
->offset
= -1;
9815 /* TODO: do these ever change? */
9817 segdir
->res0c
= 0xf;
9820 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9824 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9827 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9831 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9833 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9834 base
->memoffset
+= file_len
;
9841 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9843 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9844 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9845 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9846 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9847 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9848 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9849 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9850 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9851 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9852 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9853 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9854 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9855 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9856 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9859 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9861 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9863 DWORD written
, junk_size
, junk_offs
, running_offset
;
9870 TRACE("%p\n", This
);
9872 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
9873 if(This
->typeinfos
[i
]->needs_layout
)
9874 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
9876 memset(&file
, 0, sizeof(file
));
9878 file
.header
.magic1
= 0x5446534D;
9879 file
.header
.magic2
= 0x00010002;
9880 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9881 file
.header
.lcid2
= This
->set_lcid
;
9882 file
.header
.varflags
= 0x40 | This
->syskind
;
9884 file
.header
.varflags
|= 0x10;
9885 if (This
->HelpStringDll
)
9886 file
.header
.varflags
|= HELPDLLFLAG
;
9887 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
9888 file
.header
.flags
= This
->libflags
;
9889 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9890 file
.header
.helpcontext
= This
->dwHelpContext
;
9891 file
.header
.res44
= 0x20;
9892 file
.header
.res48
= 0x80;
9893 file
.header
.dispatchpos
= This
->dispatch_href
;
9895 WMSFT_compile_namehash(This
, &file
);
9896 /* do name and string compilation to get offsets for other compilations */
9897 hres
= WMSFT_compile_names(This
, &file
);
9899 WMSFT_free_file(&file
);
9903 hres
= WMSFT_compile_strings(This
, &file
);
9905 WMSFT_free_file(&file
);
9909 WMSFT_compile_guidhash(This
, &file
);
9910 hres
= WMSFT_compile_guids(This
, &file
);
9912 WMSFT_free_file(&file
);
9917 file
.header
.helpfile
= This
->HelpFile
->offset
;
9919 file
.header
.helpfile
= -1;
9922 file
.header
.helpstring
= This
->DocString
->offset
;
9924 file
.header
.helpstring
= -1;
9926 /* do some more segment compilation */
9927 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9928 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9931 file
.header
.NameOffset
= This
->Name
->offset
;
9933 file
.header
.NameOffset
= -1;
9935 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
9938 file
.header
.posguid
= This
->guid
->offset
;
9940 file
.header
.posguid
= -1;
9942 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9943 if(file
.header
.varflags
& HELPDLLFLAG
)
9944 junk_size
+= sizeof(DWORD
);
9946 junk
= heap_alloc_zero(junk_size
);
9947 if(file
.header
.varflags
& HELPDLLFLAG
){
9948 *junk
= This
->HelpStringDll
->offset
;
9957 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
9958 WMSFT_compile_impinfo(This
, &file
);
9962 TRACE("header at: 0x%x\n", running_offset
);
9963 running_offset
+= sizeof(file
.header
);
9965 TRACE("junk at: 0x%x\n", running_offset
);
9966 running_offset
+= junk_size
;
9968 TRACE("segdir at: 0x%x\n", running_offset
);
9969 running_offset
+= sizeof(file
.segdir
);
9971 TRACE("typeinfo at: 0x%x\n", running_offset
);
9972 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
9974 TRACE("guidhashtab at: 0x%x\n", running_offset
);
9975 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
9977 TRACE("guidtab at: 0x%x\n", running_offset
);
9978 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
9980 TRACE("reftab at: 0x%x\n", running_offset
);
9981 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
9983 TRACE("impinfo at: 0x%x\n", running_offset
);
9984 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
9986 TRACE("impfiles at: 0x%x\n", running_offset
);
9987 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
9989 TRACE("namehashtab at: 0x%x\n", running_offset
);
9990 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
9992 TRACE("nametab at: 0x%x\n", running_offset
);
9993 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
9995 TRACE("stringtab at: 0x%x\n", running_offset
);
9996 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
9998 TRACE("typdesc at: 0x%x\n", running_offset
);
9999 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10001 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10002 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10004 TRACE("custdata at: 0x%x\n", running_offset
);
10005 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10007 TRACE("cdguids at: 0x%x\n", running_offset
);
10008 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10010 TRACE("res0e at: 0x%x\n", running_offset
);
10011 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10013 TRACE("res0f at: 0x%x\n", running_offset
);
10014 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10016 TRACE("aux_seg at: 0x%x\n", running_offset
);
10018 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10020 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10021 FILE_ATTRIBUTE_NORMAL
, 0);
10022 if (outfile
== INVALID_HANDLE_VALUE
){
10023 WMSFT_free_file(&file
);
10025 return TYPE_E_IOERROR
;
10028 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10030 WMSFT_free_file(&file
);
10031 CloseHandle(outfile
);
10033 return TYPE_E_IOERROR
;
10036 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10039 WMSFT_free_file(&file
);
10040 CloseHandle(outfile
);
10041 return TYPE_E_IOERROR
;
10044 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10046 WMSFT_free_file(&file
);
10047 CloseHandle(outfile
);
10048 return TYPE_E_IOERROR
;
10051 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10052 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10053 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10054 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10055 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10056 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10057 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10058 WMSFT_write_segment(outfile
, &file
.name_seg
);
10059 WMSFT_write_segment(outfile
, &file
.string_seg
);
10060 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10061 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10062 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10063 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10064 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10066 WMSFT_free_file(&file
);
10068 CloseHandle(outfile
);
10073 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10076 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10077 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10081 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10082 REFGUID guid
, VARIANT
*varVal
)
10084 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10087 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10089 if (!guid
|| !varVal
)
10090 return E_INVALIDARG
;
10092 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10094 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10097 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10098 ULONG helpStringContext
)
10100 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10101 FIXME("%p %u - stub\n", This
, helpStringContext
);
10105 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10108 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10109 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10112 return E_INVALIDARG
;
10114 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10119 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10120 ICreateTypeLib2_fnQueryInterface
,
10121 ICreateTypeLib2_fnAddRef
,
10122 ICreateTypeLib2_fnRelease
,
10123 ICreateTypeLib2_fnCreateTypeInfo
,
10124 ICreateTypeLib2_fnSetName
,
10125 ICreateTypeLib2_fnSetVersion
,
10126 ICreateTypeLib2_fnSetGuid
,
10127 ICreateTypeLib2_fnSetDocString
,
10128 ICreateTypeLib2_fnSetHelpFileName
,
10129 ICreateTypeLib2_fnSetHelpContext
,
10130 ICreateTypeLib2_fnSetLcid
,
10131 ICreateTypeLib2_fnSetLibFlags
,
10132 ICreateTypeLib2_fnSaveAllChanges
,
10133 ICreateTypeLib2_fnDeleteTypeInfo
,
10134 ICreateTypeLib2_fnSetCustData
,
10135 ICreateTypeLib2_fnSetHelpStringContext
,
10136 ICreateTypeLib2_fnSetHelpStringDll
10139 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10140 REFIID riid
, void **object
)
10142 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10144 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10147 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10149 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10151 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10154 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10156 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10158 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10161 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10164 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10166 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10168 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10173 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10176 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10180 TRACE("%p %x\n", This
, typeFlags
);
10182 if (typeFlags
& TYPEFLAG_FDUAL
) {
10183 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10185 ITypeInfo
*dispatch
;
10189 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10193 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10194 ITypeLib_Release(stdole
);
10198 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10199 ITypeInfo_Release(dispatch
);
10204 old_flags
= This
->typeattr
.wTypeFlags
;
10205 This
->typeattr
.wTypeFlags
= typeFlags
;
10207 hres
= ICreateTypeInfo2_LayOut(iface
);
10208 if (FAILED(hres
)) {
10209 This
->typeattr
.wTypeFlags
= old_flags
;
10216 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10219 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10221 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10224 return E_INVALIDARG
;
10226 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10231 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10234 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10236 TRACE("%p %d\n", This
, helpContext
);
10238 This
->dwHelpContext
= helpContext
;
10243 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10244 WORD majorVerNum
, WORD minorVerNum
)
10246 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10248 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10250 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10251 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10256 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10257 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10259 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10261 ITypeLib
*container
;
10262 TLBRefType
*ref_type
;
10264 TYPEATTR
*typeattr
;
10268 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10270 if (!typeInfo
|| !refType
)
10271 return E_INVALIDARG
;
10273 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10277 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10278 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10280 ITypeLib_Release(container
);
10282 *refType
= target
->hreftype
;
10287 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10288 if (FAILED(hres
)) {
10289 ITypeLib_Release(container
);
10293 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10294 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10295 implib
->lcid
== libattr
->lcid
&&
10296 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10297 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10301 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10302 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10304 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10305 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10306 implib
->name
= SysAllocString(our_container
->path
);
10308 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10309 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10311 implib
->name
= NULL
;
10312 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10316 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10317 implib
->lcid
= libattr
->lcid
;
10318 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10319 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10321 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10324 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10325 ITypeLib_Release(container
);
10327 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10332 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10333 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10334 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10335 ref_type
->tkind
== typeattr
->typekind
)
10340 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10341 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10343 ref_type
->tkind
= typeattr
->typekind
;
10344 ref_type
->pImpTLInfo
= implib
;
10345 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10347 ref_type
->index
= TLB_REF_USE_GUID
;
10349 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10351 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10354 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10356 *refType
= ref_type
->reference
| 0x1;
10358 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10359 This
->pTypeLib
->dispatch_href
= *refType
;
10364 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10365 UINT index
, FUNCDESC
*funcDesc
)
10367 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10368 TLBFuncDesc tmp_func_desc
, *func_desc
;
10373 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10375 if (!funcDesc
|| funcDesc
->oVft
& 3)
10376 return E_INVALIDARG
;
10378 switch (This
->typeattr
.typekind
) {
10380 if (funcDesc
->funckind
!= FUNC_STATIC
)
10381 return TYPE_E_BADMODULEKIND
;
10383 case TKIND_DISPATCH
:
10384 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10385 return TYPE_E_BADMODULEKIND
;
10388 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10389 return TYPE_E_BADMODULEKIND
;
10392 if (index
> This
->typeattr
.cFuncs
)
10393 return TYPE_E_ELEMENTNOTFOUND
;
10395 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10396 !funcDesc
->cParams
)
10397 return TYPE_E_INCONSISTENTPROPFUNCS
;
10400 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10401 funcDesc
->oVft
% 8 != 0)
10402 return E_INVALIDARG
;
10405 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10406 TLBFuncDesc_Constructor(&tmp_func_desc
);
10408 tmp_func_desc
.funcdesc
= *funcDesc
;
10410 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10411 tmp_func_desc
.funcdesc
.oVft
|= 1;
10413 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10414 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10415 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10417 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10418 tmp_func_desc
.funcdesc
.cScodes
= 0;
10421 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10422 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10423 buf_size
+= sizeof(ELEMDESC
);
10424 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10426 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10427 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10429 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10430 if (FAILED(hres
)) {
10431 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10432 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10436 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10437 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10438 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10439 if (FAILED(hres
)) {
10440 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10441 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10444 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10445 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10446 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10447 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10448 if (FAILED(hres
)) {
10449 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10450 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10456 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10458 if (This
->funcdescs
) {
10459 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10460 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10462 if (index
< This
->typeattr
.cFuncs
) {
10463 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10464 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10465 func_desc
= This
->funcdescs
+ index
;
10467 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10469 /* move custdata lists to the new memory location */
10470 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10472 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10473 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10474 list_init(&fd
->custdata_list
);
10476 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10477 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10482 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10484 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10485 list_init(&func_desc
->custdata_list
);
10487 ++This
->typeattr
.cFuncs
;
10489 This
->needs_layout
= TRUE
;
10494 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10495 UINT index
, HREFTYPE refType
)
10497 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10498 TLBImplType
*impl_type
;
10501 TRACE("%p %u %d\n", This
, index
, refType
);
10503 switch(This
->typeattr
.typekind
){
10504 case TKIND_COCLASS
: {
10506 FIXME("Unhandled index: -1\n");
10510 if(index
!= This
->typeattr
.cImplTypes
)
10511 return TYPE_E_ELEMENTNOTFOUND
;
10515 case TKIND_INTERFACE
:
10516 case TKIND_DISPATCH
:
10517 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10518 return TYPE_E_ELEMENTNOTFOUND
;
10521 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10525 if (This
->impltypes
){
10528 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10529 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10531 if (index
< This
->typeattr
.cImplTypes
) {
10532 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10533 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10534 impl_type
= This
->impltypes
+ index
;
10536 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10538 /* move custdata lists to the new memory location */
10539 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10541 TLBImplType
*it
= &This
->impltypes
[i
];
10542 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10543 list_init(&it
->custdata_list
);
10545 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10546 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10551 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10553 memset(impl_type
, 0, sizeof(TLBImplType
));
10554 TLBImplType_Constructor(impl_type
);
10555 impl_type
->hRef
= refType
;
10557 ++This
->typeattr
.cImplTypes
;
10559 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10560 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10562 hres
= ICreateTypeInfo2_LayOut(iface
);
10569 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10570 UINT index
, INT implTypeFlags
)
10572 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10573 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10575 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10577 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10578 return TYPE_E_BADMODULEKIND
;
10580 if (index
>= This
->typeattr
.cImplTypes
)
10581 return TYPE_E_ELEMENTNOTFOUND
;
10583 impl_type
->implflags
= implTypeFlags
;
10588 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10591 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10593 TRACE("%p %d\n", This
, alignment
);
10595 This
->typeattr
.cbAlignment
= alignment
;
10600 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10603 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10605 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10608 return E_INVALIDARG
;
10610 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10612 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10617 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10618 UINT index
, VARDESC
*varDesc
)
10620 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10621 TLBVarDesc
*var_desc
;
10623 TRACE("%p %u %p\n", This
, index
, varDesc
);
10625 if (This
->vardescs
){
10628 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10629 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
10631 if (index
< This
->typeattr
.cVars
) {
10632 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10633 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
10634 var_desc
= This
->vardescs
+ index
;
10636 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
10638 /* move custdata lists to the new memory location */
10639 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
10641 TLBVarDesc
*var
= &This
->vardescs
[i
];
10642 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10643 list_init(&var
->custdata_list
);
10645 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10646 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10651 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10653 TLBVarDesc_Constructor(var_desc
);
10654 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10655 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10657 ++This
->typeattr
.cVars
;
10659 This
->needs_layout
= TRUE
;
10664 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10665 UINT index
, LPOLESTR
*names
, UINT numNames
)
10667 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10668 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10671 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10674 return E_INVALIDARG
;
10676 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
10677 return TYPE_E_ELEMENTNOTFOUND
;
10679 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10680 if(numNames
> func_desc
->funcdesc
.cParams
)
10681 return TYPE_E_ELEMENTNOTFOUND
;
10683 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10684 return TYPE_E_ELEMENTNOTFOUND
;
10686 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
10687 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10688 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10689 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10690 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10691 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10693 return TYPE_E_AMBIGUOUSNAME
;
10697 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10699 for (i
= 1; i
< numNames
; ++i
) {
10700 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10701 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10707 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10708 UINT index
, LPOLESTR name
)
10710 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10712 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10715 return E_INVALIDARG
;
10717 if(index
>= This
->typeattr
.cVars
)
10718 return TYPE_E_ELEMENTNOTFOUND
;
10720 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10724 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10725 TYPEDESC
*tdescAlias
)
10727 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10730 TRACE("%p %p\n", This
, tdescAlias
);
10733 return E_INVALIDARG
;
10735 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
10736 return TYPE_E_BADMODULEKIND
;
10738 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
10742 heap_free(This
->tdescAlias
);
10743 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10744 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10749 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10750 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10752 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10753 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10757 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10758 UINT index
, LPOLESTR docString
)
10760 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10761 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10763 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10766 return E_INVALIDARG
;
10768 if(index
>= This
->typeattr
.cFuncs
)
10769 return TYPE_E_ELEMENTNOTFOUND
;
10771 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10776 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10777 UINT index
, LPOLESTR docString
)
10779 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10780 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10782 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10785 return E_INVALIDARG
;
10787 if(index
>= This
->typeattr
.cVars
)
10788 return TYPE_E_ELEMENTNOTFOUND
;
10790 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10795 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10796 UINT index
, DWORD helpContext
)
10798 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10799 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10801 TRACE("%p %u %d\n", This
, index
, helpContext
);
10803 if(index
>= This
->typeattr
.cFuncs
)
10804 return TYPE_E_ELEMENTNOTFOUND
;
10806 func_desc
->helpcontext
= helpContext
;
10811 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10812 UINT index
, DWORD helpContext
)
10814 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10815 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10817 TRACE("%p %u %d\n", This
, index
, helpContext
);
10819 if(index
>= This
->typeattr
.cVars
)
10820 return TYPE_E_ELEMENTNOTFOUND
;
10822 var_desc
->HelpContext
= helpContext
;
10827 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10828 UINT index
, BSTR bstrMops
)
10830 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10831 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10835 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10838 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10840 TRACE("%p %p\n", This
, idlDesc
);
10843 return E_INVALIDARG
;
10845 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
10846 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10851 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10853 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10855 TLBFuncDesc
*func_desc
;
10856 UINT user_vft
= 0, i
, depth
= 0;
10857 HRESULT hres
= S_OK
;
10859 TRACE("%p\n", This
);
10861 This
->needs_layout
= FALSE
;
10863 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10867 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
10872 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10874 if (SUCCEEDED(hres
)) {
10875 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10877 if (SUCCEEDED(hres
)) {
10878 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10879 if (FAILED(hres
)) {
10880 ITypeInfo_Release(inh
);
10881 ITypeInfo_Release(tinfo
);
10884 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
10885 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10889 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10890 if(SUCCEEDED(hres
)){
10892 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10893 if(SUCCEEDED(hres
)){
10894 ITypeInfo_Release(inh
);
10898 }while(SUCCEEDED(hres
));
10901 ITypeInfo_Release(inh
);
10902 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10903 This
->typeattr
.cbSizeVft
= 0;
10906 ITypeInfo_Release(tinfo
);
10909 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10910 This
->typeattr
.cbSizeVft
= 0;
10913 ITypeInfo_Release(tinfo
);
10916 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
10917 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10919 This
->typeattr
.cbSizeVft
= 0;
10921 func_desc
= This
->funcdescs
;
10923 while (i
< This
->typeattr
.cFuncs
) {
10924 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10925 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
10927 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10928 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10930 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
10932 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10935 BOOL reset
= FALSE
;
10937 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10939 iter
= This
->funcdescs
;
10940 while (j
< This
->typeattr
.cFuncs
) {
10941 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10943 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
10946 ++func_desc
->funcdesc
.memid
;
10947 iter
= This
->funcdescs
;
10960 if (user_vft
> This
->typeattr
.cbSizeVft
)
10961 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
10963 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
10964 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
10965 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
10967 BOOL reset
= FALSE
;
10970 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
10972 iter
= This
->vardescs
;
10973 while (j
< This
->typeattr
.cVars
) {
10974 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
10976 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
10979 ++var_desc
->vardesc
.memid
;
10980 iter
= This
->vardescs
;
10990 ITypeInfo_Release(tinfo
);
10994 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
10997 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10998 FIXME("%p %u - stub\n", This
, index
);
11002 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11003 MEMBERID memid
, INVOKEKIND invKind
)
11005 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11006 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11010 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11013 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11014 FIXME("%p %u - stub\n", This
, index
);
11018 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11021 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11022 FIXME("%p %x - stub\n", This
, memid
);
11026 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11029 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11030 FIXME("%p %u - stub\n", This
, index
);
11034 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11035 REFGUID guid
, VARIANT
*varVal
)
11039 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11041 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11043 if (!guid
|| !varVal
)
11044 return E_INVALIDARG
;
11046 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11048 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11051 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11052 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11054 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11055 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11059 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11060 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11062 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11063 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11067 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11068 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11070 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11071 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11075 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11076 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11078 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11079 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11083 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11084 ULONG helpStringContext
)
11086 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11088 TRACE("%p %u\n", This
, helpStringContext
);
11090 This
->dwHelpStringContext
= helpStringContext
;
11095 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11096 UINT index
, ULONG helpStringContext
)
11098 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11099 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11103 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11104 UINT index
, ULONG helpStringContext
)
11106 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11107 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11111 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11113 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11114 FIXME("%p - stub\n", This
);
11118 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11121 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11123 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11126 return E_INVALIDARG
;
11128 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11133 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11134 ICreateTypeInfo2_fnQueryInterface
,
11135 ICreateTypeInfo2_fnAddRef
,
11136 ICreateTypeInfo2_fnRelease
,
11137 ICreateTypeInfo2_fnSetGuid
,
11138 ICreateTypeInfo2_fnSetTypeFlags
,
11139 ICreateTypeInfo2_fnSetDocString
,
11140 ICreateTypeInfo2_fnSetHelpContext
,
11141 ICreateTypeInfo2_fnSetVersion
,
11142 ICreateTypeInfo2_fnAddRefTypeInfo
,
11143 ICreateTypeInfo2_fnAddFuncDesc
,
11144 ICreateTypeInfo2_fnAddImplType
,
11145 ICreateTypeInfo2_fnSetImplTypeFlags
,
11146 ICreateTypeInfo2_fnSetAlignment
,
11147 ICreateTypeInfo2_fnSetSchema
,
11148 ICreateTypeInfo2_fnAddVarDesc
,
11149 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11150 ICreateTypeInfo2_fnSetVarName
,
11151 ICreateTypeInfo2_fnSetTypeDescAlias
,
11152 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11153 ICreateTypeInfo2_fnSetFuncDocString
,
11154 ICreateTypeInfo2_fnSetVarDocString
,
11155 ICreateTypeInfo2_fnSetFuncHelpContext
,
11156 ICreateTypeInfo2_fnSetVarHelpContext
,
11157 ICreateTypeInfo2_fnSetMops
,
11158 ICreateTypeInfo2_fnSetTypeIdldesc
,
11159 ICreateTypeInfo2_fnLayOut
,
11160 ICreateTypeInfo2_fnDeleteFuncDesc
,
11161 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11162 ICreateTypeInfo2_fnDeleteVarDesc
,
11163 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11164 ICreateTypeInfo2_fnDeleteImplType
,
11165 ICreateTypeInfo2_fnSetCustData
,
11166 ICreateTypeInfo2_fnSetFuncCustData
,
11167 ICreateTypeInfo2_fnSetParamCustData
,
11168 ICreateTypeInfo2_fnSetVarCustData
,
11169 ICreateTypeInfo2_fnSetImplTypeCustData
,
11170 ICreateTypeInfo2_fnSetHelpStringContext
,
11171 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11172 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11173 ICreateTypeInfo2_fnInvalidate
,
11174 ICreateTypeInfo2_fnSetName
11177 /******************************************************************************
11178 * ClearCustData (OLEAUT32.171)
11180 * Clear a custom data type's data.
11183 * lpCust [I] The custom data type instance
11188 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11190 if (lpCust
&& lpCust
->cCustData
)
11192 if (lpCust
->prgCustData
)
11196 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11197 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11199 CoTaskMemFree(lpCust
->prgCustData
);
11200 lpCust
->prgCustData
= NULL
;
11202 lpCust
->cCustData
= 0;