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/heap.h"
77 #include "wine/list.h"
79 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
80 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
94 WORD type_id
; /* Type identifier */
95 WORD count
; /* Number of resources of this type */
96 DWORD resloader
; /* SetResourceHandler() */
102 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
103 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
104 static void TLB_FreeVarDesc(VARDESC
*);
106 /****************************************************************************
109 * Takes p_iVal (which is in little endian) and returns it
110 * in the host machine's byte order.
112 #ifdef WORDS_BIGENDIAN
113 static WORD
FromLEWord(WORD p_iVal
)
115 return (((p_iVal
& 0x00FF) << 8) |
116 ((p_iVal
& 0xFF00) >> 8));
120 static DWORD
FromLEDWord(DWORD p_iVal
)
122 return (((p_iVal
& 0x000000FF) << 24) |
123 ((p_iVal
& 0x0000FF00) << 8) |
124 ((p_iVal
& 0x00FF0000) >> 8) |
125 ((p_iVal
& 0xFF000000) >> 24));
128 #define FromLEWord(X) (X)
129 #define FromLEDWord(X) (X)
132 #define DISPATCH_HREF_OFFSET 0x01000000
133 #define DISPATCH_HREF_MASK 0xff000000
135 /****************************************************************************
138 * Fix byte order in any structure if necessary
140 #ifdef WORDS_BIGENDIAN
141 static void FromLEWords(void *p_Val
, int p_iSize
)
145 p_iSize
/= sizeof(WORD
);
148 *Val
= FromLEWord(*Val
);
155 static void FromLEDWords(void *p_Val
, int p_iSize
)
159 p_iSize
/= sizeof(DWORD
);
162 *Val
= FromLEDWord(*Val
);
168 #define FromLEWords(X,Y) /*nothing*/
169 #define FromLEDWords(X,Y) /*nothing*/
173 * Find a typelib key which matches a requested maj.min version.
175 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
177 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
181 INT best_maj
= -1, best_min
= -1;
184 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
185 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
187 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
190 len
= sizeof(key_name
);
192 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
196 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
198 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
200 if (*wMaj
== 0xffff && *wMin
== 0xffff)
202 if (v_maj
> best_maj
) best_maj
= v_maj
;
203 if (v_min
> best_min
) best_min
= v_min
;
205 else if (*wMaj
== v_maj
)
212 break; /* exact match */
214 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
217 len
= sizeof(key_name
);
221 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
223 if (*wMaj
== 0xffff && *wMin
== 0xffff)
225 if (best_maj
>= 0 && best_min
>= 0)
233 if (*wMaj
== best_maj
&& best_min
>= 0)
241 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
242 /* buffer must be at least 60 characters long */
243 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
245 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
246 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
248 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
249 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
250 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
254 /* get the path of an interface key, in the form "Interface\\<guid>" */
255 /* buffer must be at least 50 characters long */
256 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
258 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
260 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
261 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
265 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
266 /* buffer must be at least 16 characters long */
267 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
269 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
270 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
271 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
272 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
274 sprintfW( buffer
, LcidFormatW
, lcid
);
277 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
278 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
279 case SYS_WIN64
: strcatW( buffer
, win64W
); break;
281 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
287 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
289 struct tlibredirect_data
303 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
304 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
305 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
307 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
311 WCHAR Path
[MAX_PATH
];
314 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
318 ACTCTX_SECTION_KEYED_DATA data
;
320 data
.cbSize
= sizeof(data
);
321 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
323 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
327 if ((wMaj
!= 0xffff || wMin
!= 0xffff) && (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
))
328 return TYPE_E_LIBNOTREGISTERED
;
330 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
331 len
= SearchPathW( NULL
, nameW
, NULL
, ARRAY_SIZE( Path
), Path
, NULL
);
332 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
334 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
335 *path
= SysAllocString( Path
);
340 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
341 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
343 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
344 if (res
== ERROR_FILE_NOT_FOUND
)
346 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
347 return TYPE_E_LIBNOTREGISTERED
;
349 else if (res
!= ERROR_SUCCESS
)
351 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
352 return TYPE_E_REGISTRYACCESS
;
357 LONG dwPathLen
= sizeof(Path
);
359 get_lcid_subkey( myLCID
, syskind
, buffer
);
361 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
365 else if (myLCID
== lcid
)
367 /* try with sub-langid */
368 myLCID
= SUBLANGID(lcid
);
370 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
372 /* try with system langid */
382 *path
= SysAllocString( Path
);
387 TRACE_(typelib
)("-- 0x%08x\n", hr
);
391 /****************************************************************************
392 * QueryPathOfRegTypeLib [OLEAUT32.164]
394 * Gets the path to a registered type library.
397 * guid [I] referenced guid
398 * wMaj [I] major version
399 * wMin [I] minor version
401 * path [O] path of typelib
405 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
406 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
409 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
413 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
418 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
421 /******************************************************************************
422 * CreateTypeLib [OLEAUT32.160] creates a typelib
428 HRESULT WINAPI
CreateTypeLib(
429 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
431 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
435 /******************************************************************************
436 * LoadTypeLib [OLEAUT32.161]
438 * Loads a type library
441 * szFile [I] Name of file to load from.
442 * pptLib [O] Pointer that receives ITypeLib object on success.
449 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
451 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
453 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
454 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
457 /******************************************************************************
458 * LoadTypeLibEx [OLEAUT32.183]
460 * Loads and optionally registers a type library
466 HRESULT WINAPI
LoadTypeLibEx(
467 LPCOLESTR szFile
, /* [in] Name of file to load from */
468 REGKIND regkind
, /* [in] Specify kind of registration */
469 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
471 WCHAR szPath
[MAX_PATH
+1];
474 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
476 if (!szFile
|| !pptLib
)
481 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
486 case REGKIND_DEFAULT
:
487 /* don't register typelibs supplied with full path. Experimentation confirms the following */
488 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
489 (szFile
[0] && (szFile
[1] == ':'))) break;
490 /* else fall-through */
492 case REGKIND_REGISTER
:
493 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
495 ITypeLib_Release(*pptLib
);
503 TRACE(" returns %08x\n",res
);
507 /******************************************************************************
508 * LoadRegTypeLib [OLEAUT32.162]
510 * Loads a registered type library.
513 * rguid [I] GUID of the registered type library.
514 * wVerMajor [I] major version.
515 * wVerMinor [I] minor version.
516 * lcid [I] locale ID.
517 * ppTLib [O] pointer that receives an ITypeLib object on success.
521 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
524 HRESULT WINAPI
LoadRegTypeLib(
536 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
540 res
= LoadTypeLib(bstr
, ppTLib
);
543 if ((wVerMajor
!=0xffff || wVerMinor
!=0xffff) && *ppTLib
)
547 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
550 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
551 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
555 ITypeLib_Release(*ppTLib
);
557 res
= TYPE_E_LIBNOTREGISTERED
;
563 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
569 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
570 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
571 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
572 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
573 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
574 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
576 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
581 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
582 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
583 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
585 get_interface_key( &tattr
->guid
, keyName
);
586 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
587 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
590 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
591 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
593 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
594 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
595 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
596 (const BYTE
*)PSOA
, sizeof PSOA
);
600 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
601 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
602 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
603 (const BYTE
*)PSOA
, sizeof PSOA
);
607 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
608 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
611 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
612 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
614 StringFromGUID2(&libattr
->guid
, buffer
, 40);
615 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
616 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
617 sprintfW(buffer
, fmtver
, libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
618 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
619 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
627 /******************************************************************************
628 * RegisterTypeLib [OLEAUT32.163]
629 * Adds information about a type library to the System Registry
631 * Docs: ITypeLib FAR * ptlib
632 * Docs: OLECHAR FAR* szFullPath
633 * Docs: OLECHAR FAR* szHelpDir
639 HRESULT WINAPI
RegisterTypeLib(
640 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
641 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
642 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
654 if (ptlib
== NULL
|| szFullPath
== NULL
)
657 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
661 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
664 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
667 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
668 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
672 /* Set the human-readable name of the typelib */
673 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
677 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
678 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
684 /* Make up the name of the typelib path subkey */
685 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
687 /* Create the typelib path subkey */
688 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
689 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
691 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
692 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
700 /* Create the flags subkey */
701 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
702 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
704 /* FIXME: is %u correct? */
705 static const WCHAR formatW
[] = {'%','u',0};
707 sprintfW(buf
, formatW
, attr
->wLibFlags
);
708 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
709 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
717 /* create the helpdir subkey */
718 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
719 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
721 BOOL freeHelpDir
= FALSE
;
724 /* if we created a new key, and helpDir was null, set the helpdir
725 to the directory which contains the typelib. However,
726 if we just opened an existing key, we leave the helpdir alone */
727 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
728 szHelpDir
= SysAllocString(szFullPath
);
729 pIndexStr
= strrchrW(szHelpDir
, '\\');
736 /* if we have an szHelpDir, set it! */
737 if (szHelpDir
!= NULL
) {
738 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
739 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
745 if (freeHelpDir
) SysFreeString(szHelpDir
);
757 /* register OLE Automation-compatible interfaces for this typelib */
758 types
= ITypeLib_GetTypeInfoCount(ptlib
);
759 for (tidx
=0; tidx
<types
; tidx
++) {
760 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
761 LPOLESTR name
= NULL
;
762 ITypeInfo
*tinfo
= NULL
;
764 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
767 case TKIND_INTERFACE
:
768 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
769 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
773 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
774 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
778 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
783 TYPEATTR
*tattr
= NULL
;
784 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
787 TRACE_(typelib
)("guid=%s, flags=%04x (",
788 debugstr_guid(&tattr
->guid
),
791 if (TRACE_ON(typelib
)) {
792 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
812 /* Register all dispinterfaces (which includes dual interfaces) and
813 oleautomation interfaces */
814 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
815 kind
== TKIND_DISPATCH
)
818 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
820 /* register interface<->typelib coupling */
821 TLB_register_interface(attr
, name
, tattr
, 0);
823 /* register TLBs into the opposite registry view, too */
824 if(opposite
== KEY_WOW64_32KEY
||
825 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
826 TLB_register_interface(attr
, name
, tattr
, opposite
);
829 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
832 ITypeInfo_Release(tinfo
);
839 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
844 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
846 WCHAR subKeyName
[50];
849 /* the path to the type */
850 get_interface_key( guid
, subKeyName
);
852 /* Delete its bits */
853 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
856 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
857 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
858 RegDeleteKeyW(subKey
, TypeLibW
);
860 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
863 /******************************************************************************
864 * UnRegisterTypeLib [OLEAUT32.186]
865 * Removes information about a type library from the System Registry
872 HRESULT WINAPI
UnRegisterTypeLib(
873 REFGUID libid
, /* [in] Guid of the library */
874 WORD wVerMajor
, /* [in] major version */
875 WORD wVerMinor
, /* [in] minor version */
876 LCID lcid
, /* [in] locale id */
879 BSTR tlibPath
= NULL
;
882 WCHAR subKeyName
[50];
885 BOOL deleteOtherStuff
;
887 TYPEATTR
* typeAttr
= NULL
;
889 ITypeInfo
* typeInfo
= NULL
;
890 ITypeLib
* typeLib
= NULL
;
893 TRACE("(IID: %s)\n",debugstr_guid(libid
));
895 /* Create the path to the key */
896 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
898 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
900 TRACE("Unsupported syskind %i\n", syskind
);
901 result
= E_INVALIDARG
;
905 /* get the path to the typelib on disk */
906 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
907 result
= E_INVALIDARG
;
911 /* Try and open the key to the type library. */
912 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
913 result
= E_INVALIDARG
;
917 /* Try and load the type library */
918 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
919 result
= TYPE_E_INVALIDSTATE
;
923 /* remove any types registered with this typelib */
924 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
925 for (i
=0; i
<numTypes
; i
++) {
926 /* get the kind of type */
927 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
931 /* skip non-interfaces, and get type info for the type */
932 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
935 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
938 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
942 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
943 kind
== TKIND_DISPATCH
)
946 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
948 TLB_unregister_interface(&typeAttr
->guid
, 0);
950 /* unregister TLBs into the opposite registry view, too */
951 if(opposite
== KEY_WOW64_32KEY
||
952 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
953 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
958 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
960 if (typeInfo
) ITypeInfo_Release(typeInfo
);
964 /* Now, delete the type library path subkey */
965 get_lcid_subkey( lcid
, syskind
, subKeyName
);
966 RegDeleteKeyW(key
, subKeyName
);
967 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
968 RegDeleteKeyW(key
, subKeyName
);
970 /* check if there is anything besides the FLAGS/HELPDIR keys.
971 If there is, we don't delete them */
972 tmpLength
= ARRAY_SIZE(subKeyName
);
973 deleteOtherStuff
= TRUE
;
975 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
976 tmpLength
= ARRAY_SIZE(subKeyName
);
978 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
979 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
980 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
981 deleteOtherStuff
= FALSE
;
985 /* only delete the other parts of the key if we're absolutely sure */
986 if (deleteOtherStuff
) {
987 RegDeleteKeyW(key
, FLAGSW
);
988 RegDeleteKeyW(key
, HELPDIRW
);
992 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
993 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
994 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
998 SysFreeString(tlibPath
);
999 if (typeLib
) ITypeLib_Release(typeLib
);
1000 if (key
) RegCloseKey(key
);
1004 /******************************************************************************
1005 * RegisterTypeLibForUser [OLEAUT32.442]
1006 * Adds information about a type library to the user registry
1008 * Docs: ITypeLib FAR * ptlib
1009 * Docs: OLECHAR FAR* szFullPath
1010 * Docs: OLECHAR FAR* szHelpDir
1016 HRESULT WINAPI
RegisterTypeLibForUser(
1017 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
1018 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
1019 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1022 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1023 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1024 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1027 /******************************************************************************
1028 * UnRegisterTypeLibForUser [OLEAUT32.443]
1029 * Removes information about a type library from the user registry
1035 HRESULT WINAPI
UnRegisterTypeLibForUser(
1036 REFGUID libid
, /* [in] GUID of the library */
1037 WORD wVerMajor
, /* [in] major version */
1038 WORD wVerMinor
, /* [in] minor version */
1039 LCID lcid
, /* [in] locale id */
1042 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1043 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1044 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1047 /*======================= ITypeLib implementation =======================*/
1049 typedef struct tagTLBGuid
{
1056 typedef struct tagTLBCustData
1063 /* data structure for import typelibs */
1064 typedef struct tagTLBImpLib
1066 int offset
; /* offset in the file (MSFT)
1067 offset in nametable (SLTG)
1068 just used to identify library while reading
1070 TLBGuid
*guid
; /* libid */
1071 BSTR name
; /* name */
1073 LCID lcid
; /* lcid of imported typelib */
1075 WORD wVersionMajor
; /* major version number */
1076 WORD wVersionMinor
; /* minor version number */
1078 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1079 NULL if not yet loaded */
1083 typedef struct tagTLBString
{
1089 /* internal ITypeLib data */
1090 typedef struct tagITypeLibImpl
1092 ITypeLib2 ITypeLib2_iface
;
1093 ITypeComp ITypeComp_iface
;
1094 ICreateTypeLib2 ICreateTypeLib2_iface
;
1105 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1106 * exported to the application as a UNICODE string.
1108 struct list string_list
;
1109 struct list name_list
;
1110 struct list guid_list
;
1112 const TLBString
*Name
;
1113 const TLBString
*DocString
;
1114 const TLBString
*HelpFile
;
1115 const TLBString
*HelpStringDll
;
1116 DWORD dwHelpContext
;
1117 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1118 struct tagITypeInfoImpl
**typeinfos
;
1119 struct list custdata_list
;
1120 struct list implib_list
;
1121 int ctTypeDesc
; /* number of items in type desc array */
1122 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1123 library. Only used while reading MSFT
1125 struct list ref_list
; /* list of ref types in this typelib */
1126 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1129 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1135 static const ITypeLib2Vtbl tlbvt
;
1136 static const ITypeCompVtbl tlbtcvt
;
1137 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1139 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1141 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1144 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1146 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1149 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1151 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1154 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1156 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1159 /* ITypeLib methods */
1160 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1161 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1163 /*======================= ITypeInfo implementation =======================*/
1165 /* data for referenced types */
1166 typedef struct tagTLBRefType
1168 INT index
; /* Type index for internal ref or for external ref
1169 it the format is SLTG. -2 indicates to
1173 TLBGuid
*guid
; /* guid of the referenced type */
1174 /* if index == TLB_REF_USE_GUID */
1176 HREFTYPE reference
; /* The href of this ref */
1177 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1178 TLB_REF_INTERNAL for internal refs
1179 TLB_REF_NOT_FOUND for broken refs */
1184 #define TLB_REF_USE_GUID -2
1186 #define TLB_REF_INTERNAL (void*)-2
1187 #define TLB_REF_NOT_FOUND (void*)-1
1189 /* internal Parameter data */
1190 typedef struct tagTLBParDesc
1192 const TLBString
*Name
;
1193 struct list custdata_list
;
1196 /* internal Function data */
1197 typedef struct tagTLBFuncDesc
1199 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1200 const TLBString
*Name
; /* the name of this function */
1201 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1203 int HelpStringContext
;
1204 const TLBString
*HelpString
;
1205 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1206 struct list custdata_list
;
1209 /* internal Variable data */
1210 typedef struct tagTLBVarDesc
1212 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1213 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1214 const TLBString
*Name
; /* the name of this variable */
1216 int HelpStringContext
;
1217 const TLBString
*HelpString
;
1218 struct list custdata_list
;
1221 /* internal implemented interface data */
1222 typedef struct tagTLBImplType
1224 HREFTYPE hRef
; /* hRef of interface */
1225 int implflags
; /* IMPLFLAG_*s */
1226 struct list custdata_list
;
1229 /* internal TypeInfo data */
1230 typedef struct tagITypeInfoImpl
1232 ITypeInfo2 ITypeInfo2_iface
;
1233 ITypeComp ITypeComp_iface
;
1234 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1236 BOOL not_attached_to_typelib
;
1241 TYPEDESC
*tdescAlias
;
1243 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1244 int index
; /* index in this typelib; */
1245 HREFTYPE hreftype
; /* hreftype for app object binding */
1246 /* type libs seem to store the doc strings in ascii
1247 * so why should we do it in unicode?
1249 const TLBString
*Name
;
1250 const TLBString
*DocString
;
1251 const TLBString
*DllName
;
1252 const TLBString
*Schema
;
1253 DWORD dwHelpContext
;
1254 DWORD dwHelpStringContext
;
1257 TLBFuncDesc
*funcdescs
;
1260 TLBVarDesc
*vardescs
;
1262 /* Implemented Interfaces */
1263 TLBImplType
*impltypes
;
1265 struct list
*pcustdata_list
;
1266 struct list custdata_list
;
1269 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1271 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1274 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1276 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1279 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1281 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1284 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1286 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1289 static const ITypeInfo2Vtbl tinfvt
;
1290 static const ITypeCompVtbl tcompvt
;
1291 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1293 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1294 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1296 typedef struct tagTLBContext
1298 unsigned int oStart
; /* start of TLB in file */
1299 unsigned int pos
; /* current pos */
1300 unsigned int length
; /* total length */
1301 void *mapping
; /* memory mapping */
1302 MSFT_SegDir
* pTblDir
;
1303 ITypeLibImpl
* pLibInfo
;
1307 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1309 return str
!= NULL
? str
->str
: NULL
;
1312 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1316 return memcmp(left
, str
->str
, len
);
1319 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1321 return guid
!= NULL
? &guid
->guid
: NULL
;
1324 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1326 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1329 static int get_ptr_size(SYSKIND syskind
)
1339 WARN("Unhandled syskind: 0x%x\n", syskind
);
1346 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1347 if (pTD
->vt
& VT_RESERVED
)
1348 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1349 if (pTD
->vt
& VT_BYREF
)
1350 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1351 if (pTD
->vt
& VT_ARRAY
)
1352 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1353 if (pTD
->vt
& VT_VECTOR
)
1354 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1355 switch(pTD
->vt
& VT_TYPEMASK
) {
1356 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1357 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1358 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1359 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1360 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1361 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1362 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1363 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1364 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1365 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1366 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1367 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1368 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1369 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1370 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1371 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1372 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1373 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1374 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1375 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1376 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1377 pTD
->u
.hreftype
); break;
1378 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1379 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1380 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1381 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1383 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1384 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1386 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1387 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1388 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1391 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1395 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1397 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1398 dump_TypeDesc(&edesc
->tdesc
,buf
);
1399 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1400 MESSAGE("\t\tu.paramdesc.wParamFlags");
1401 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1402 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1403 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1404 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1405 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1406 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1407 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1408 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1409 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1411 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1413 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1414 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1415 MESSAGE("Param %d:\n",i
);
1416 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1418 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1419 switch (funcdesc
->funckind
) {
1420 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1421 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1422 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1423 case FUNC_STATIC
: MESSAGE("static");break;
1424 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1425 default: MESSAGE("unknown");break;
1427 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1428 switch (funcdesc
->invkind
) {
1429 case INVOKE_FUNC
: MESSAGE("func");break;
1430 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1431 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1432 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1434 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1435 switch (funcdesc
->callconv
) {
1436 case CC_CDECL
: MESSAGE("cdecl");break;
1437 case CC_PASCAL
: MESSAGE("pascal");break;
1438 case CC_STDCALL
: MESSAGE("stdcall");break;
1439 case CC_SYSCALL
: MESSAGE("syscall");break;
1442 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1443 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1444 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1446 MESSAGE("\telemdescFunc (return value type):\n");
1447 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1450 static const char * const typekind_desc
[] =
1463 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1466 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1467 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1468 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1471 dump_FUNCDESC(&(pfd
->funcdesc
));
1473 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1474 if(pfd
->Entry
== NULL
)
1475 MESSAGE("\tentry: (null)\n");
1476 else if(pfd
->Entry
== (void*)-1)
1477 MESSAGE("\tentry: invalid\n");
1478 else if(IS_INTRESOURCE(pfd
->Entry
))
1479 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1481 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1483 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1487 dump_TLBFuncDescOne(pfd
);
1492 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1496 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1502 static void dump_TLBImpLib(const TLBImpLib
*import
)
1504 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1505 debugstr_w(import
->name
));
1506 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1507 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1510 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1514 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1516 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1517 if(ref
->index
== -1)
1518 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1520 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1522 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1524 TRACE_(typelib
)("in lib\n");
1525 dump_TLBImpLib(ref
->pImpTLInfo
);
1530 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1535 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1536 impl
->hRef
, impl
->implflags
);
1542 static void dump_DispParms(const DISPPARAMS
* pdp
)
1546 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1548 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1550 TRACE("named args:\n");
1551 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1552 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1555 if (pdp
->cArgs
&& pdp
->rgvarg
)
1558 for (index
= 0; index
< pdp
->cArgs
; index
++)
1559 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1563 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1565 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1566 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1567 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1568 TRACE("kind:%s\n", typekind_desc
[pty
->typeattr
.typekind
]);
1569 TRACE("fct:%u var:%u impl:%u\n", pty
->typeattr
.cFuncs
, pty
->typeattr
.cVars
, pty
->typeattr
.cImplTypes
);
1570 TRACE("wTypeFlags: 0x%04x\n", pty
->typeattr
.wTypeFlags
);
1571 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1572 if (pty
->typeattr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1574 dump_TLBFuncDesc(pty
->funcdescs
, pty
->typeattr
.cFuncs
);
1575 dump_TLBVarDesc(pty
->vardescs
, pty
->typeattr
.cVars
);
1576 dump_TLBImplType(pty
->impltypes
, pty
->typeattr
.cImplTypes
);
1579 static void dump_VARDESC(const VARDESC
*v
)
1581 MESSAGE("memid %d\n",v
->memid
);
1582 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1583 MESSAGE("oInst %d\n",v
->u
.oInst
);
1584 dump_ELEMDESC(&(v
->elemdescVar
));
1585 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1586 MESSAGE("varkind %d\n",v
->varkind
);
1589 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1591 /* VT_LPWSTR is largest type that, may appear in type description */
1592 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1593 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1594 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1595 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1596 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1597 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1598 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1599 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1602 static void TLB_abort(void)
1607 /* returns the size required for a deep copy of a typedesc into a
1609 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1613 if (alloc_initial_space
)
1614 size
+= sizeof(TYPEDESC
);
1620 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1623 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1624 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1630 /* deep copy a typedesc into a flat buffer */
1631 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1636 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1645 dest
->u
.lptdesc
= buffer
;
1646 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1649 dest
->u
.lpadesc
= buffer
;
1650 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1651 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1652 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1658 /* free custom data allocated by MSFT_CustData */
1659 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1661 TLBCustData
*cd
, *cdn
;
1662 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1664 list_remove(&cd
->entry
);
1665 VariantClear(&cd
->data
);
1670 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1675 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1676 ret
= SysAllocStringLen(NULL
, len
- 1);
1677 if (!ret
) return ret
;
1678 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1682 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1683 UINT n
, MEMBERID memid
)
1686 if(funcdescs
->funcdesc
.memid
== memid
)
1694 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1695 UINT n
, MEMBERID memid
)
1698 if(vardescs
->vardesc
.memid
== memid
)
1706 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1707 UINT n
, const OLECHAR
*name
)
1710 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1718 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1720 TLBCustData
*cust_data
;
1721 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1722 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1727 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1728 UINT n
, const OLECHAR
*name
)
1731 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1739 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1741 list_init(&var_desc
->custdata_list
);
1744 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1748 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1753 TLBVarDesc_Constructor(&ret
[n
-1]);
1760 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1764 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1769 list_init(&ret
[n
-1].custdata_list
);
1776 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1778 list_init(&func_desc
->custdata_list
);
1781 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1785 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1790 TLBFuncDesc_Constructor(&ret
[n
-1]);
1797 static void TLBImplType_Constructor(TLBImplType
*impl
)
1799 list_init(&impl
->custdata_list
);
1802 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1806 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1811 TLBImplType_Constructor(&ret
[n
-1]);
1818 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1819 const GUID
*new_guid
, HREFTYPE hreftype
)
1823 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1824 if (IsEqualGUID(&guid
->guid
, new_guid
))
1828 guid
= heap_alloc(sizeof(TLBGuid
));
1832 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1833 guid
->hreftype
= hreftype
;
1835 list_add_tail(guid_list
, &guid
->entry
);
1840 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1842 TLBCustData
*cust_data
;
1854 return DISP_E_BADVARTYPE
;
1857 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1860 cust_data
= heap_alloc(sizeof(TLBCustData
));
1862 return E_OUTOFMEMORY
;
1864 cust_data
->guid
= tlbguid
;
1865 VariantInit(&cust_data
->data
);
1867 list_add_tail(custdata_list
, &cust_data
->entry
);
1869 VariantClear(&cust_data
->data
);
1871 return VariantCopy(&cust_data
->data
, var
);
1874 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1881 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1882 if (strcmpW(str
->str
, new_str
) == 0)
1886 str
= heap_alloc(sizeof(TLBString
));
1890 str
->str
= SysAllocString(new_str
);
1896 list_add_tail(string_list
, &str
->entry
);
1901 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1902 ULONG
*size
, WORD
*align
)
1908 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1912 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1914 ITypeInfo_Release(other
);
1919 *size
= attr
->cbSizeInstance
;
1921 *align
= attr
->cbAlignment
;
1923 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1924 ITypeInfo_Release(other
);
1929 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1930 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1932 ULONG i
, sub
, ptr_size
;
1935 ptr_size
= get_ptr_size(sys
);
1974 *size
= sizeof(DATE
);
1977 *size
= sizeof(VARIANT
);
1979 if(sys
== SYS_WIN32
)
1980 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1984 *size
= sizeof(DECIMAL
);
1991 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
1992 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
1993 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
1998 case VT_USERDEFINED
:
1999 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2001 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2015 /**********************************************************************
2017 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2020 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2022 if (where
!= DO_NOT_SEEK
)
2024 where
+= pcx
->oStart
;
2025 if (where
> pcx
->length
)
2028 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2036 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2038 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2039 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2041 MSFT_Seek(pcx
, where
);
2042 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2043 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2048 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2053 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2054 FromLEDWords(buffer
, ret
);
2059 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2064 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2065 FromLEWords(buffer
, ret
);
2070 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2073 MSFT_GuidEntry entry
;
2076 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2078 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2081 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2083 guid
= heap_alloc(sizeof(TLBGuid
));
2085 guid
->offset
= offs
;
2086 guid
->guid
= entry
.guid
;
2087 guid
->hreftype
= entry
.hreftype
;
2089 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2091 offs
+= sizeof(MSFT_GuidEntry
);
2095 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2099 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2100 if(ret
->offset
== offset
){
2101 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2109 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2111 MSFT_NameIntro niName
;
2115 ERR_(typelib
)("bad offset %d\n", offset
);
2119 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2120 pcx
->pTblDir
->pNametab
.offset
+offset
);
2122 return niName
.hreftype
;
2125 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2128 MSFT_NameIntro intro
;
2130 int offs
= 0, lengthInChars
;
2132 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2136 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2139 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2140 intro
.namelen
&= 0xFF;
2141 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2143 len_piece
= (len_piece
+ 4) & ~0x3;
2147 string
= heap_alloc(len_piece
+ 1);
2148 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2149 string
[intro
.namelen
] = '\0';
2151 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2152 string
, -1, NULL
, 0);
2153 if (!lengthInChars
) {
2155 return E_UNEXPECTED
;
2158 tlbstr
= heap_alloc(sizeof(TLBString
));
2160 tlbstr
->offset
= offs
;
2161 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2162 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2166 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2172 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2176 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2177 if (tlbstr
->offset
== offset
) {
2178 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2186 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2190 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2191 if (tlbstr
->offset
== offset
) {
2192 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2201 * read a value and fill a VARIANT structure
2203 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2207 TRACE_(typelib
)("\n");
2209 if(offset
<0) { /* data are packed in here */
2210 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2211 V_I4(pVar
) = offset
& 0x3ffffff;
2214 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2215 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2216 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2217 switch (V_VT(pVar
)){
2218 case VT_EMPTY
: /* FIXME: is this right? */
2219 case VT_NULL
: /* FIXME: is this right? */
2220 case VT_I2
: /* this should not happen */
2231 case VT_VOID
: /* FIXME: is this right? */
2239 case VT_DECIMAL
: /* FIXME: is this right? */
2242 /* pointer types with known behaviour */
2245 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2247 V_BSTR(pVar
) = NULL
;
2249 ptr
= heap_alloc_zero(size
);
2250 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2251 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2252 /* FIXME: do we need a AtoW conversion here? */
2253 V_UNION(pVar
, bstrVal
[size
])='\0';
2254 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2259 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2266 case VT_USERDEFINED
:
2272 case VT_STREAMED_OBJECT
:
2273 case VT_STORED_OBJECT
:
2274 case VT_BLOB_OBJECT
:
2279 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2283 if(size
>0) /* (big|small) endian correct? */
2284 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2288 * create a linked list with custom data
2290 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2296 TRACE_(typelib
)("\n");
2298 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2302 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2303 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2304 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2305 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2306 list_add_head(custdata_list
, &pNew
->entry
);
2307 offset
= entry
.next
;
2312 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2315 pTd
->vt
=type
& VT_TYPEMASK
;
2317 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2319 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2322 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2324 return (invkind
== INVOKE_PROPERTYGET
||
2325 invkind
== INVOKE_PROPERTYPUT
||
2326 invkind
== INVOKE_PROPERTYPUTREF
);
2330 MSFT_DoFuncs(TLBContext
* pcx
,
2335 TLBFuncDesc
** pptfd
)
2338 * member information is stored in a data structure at offset
2339 * indicated by the memoffset field of the typeinfo structure
2340 * There are several distinctive parts.
2341 * The first part starts with a field that holds the total length
2342 * of this (first) part excluding this field. Then follow the records,
2343 * for each member there is one record.
2345 * The first entry is always the length of the record (including this
2347 * The rest of the record depends on the type of the member. If there is
2348 * a field indicating the member type (function, variable, interface, etc)
2349 * I have not found it yet. At this time we depend on the information
2350 * in the type info and the usual order how things are stored.
2352 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2355 * Third is an equal sized array with file offsets to the name entry
2358 * The fourth and last (?) part is an array with offsets to the records
2359 * in the first part of this file segment.
2362 int infolen
, nameoffset
, reclength
, i
;
2363 int recoffset
= offset
+ sizeof(INT
);
2365 char *recbuf
= heap_alloc(0xffff);
2366 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2367 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2369 TRACE_(typelib
)("\n");
2371 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2373 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2375 for ( i
= 0; i
< cFuncs
; i
++ )
2379 /* name, eventually add to a hash table */
2380 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2381 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2383 /* read the function information record */
2384 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2386 reclength
&= 0xffff;
2388 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2390 /* size without argument data */
2391 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2392 if (pFuncRec
->FKCCIC
& 0x1000)
2393 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2395 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2396 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2398 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2399 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2401 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2403 if (pFuncRec
->FKCCIC
& 0x2000 )
2405 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2406 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2407 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2410 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2413 ptfd
->Entry
= (TLBString
*)-1;
2415 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2416 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2418 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2419 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2421 /* fill the FuncDesc Structure */
2422 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2423 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2425 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2426 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2427 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2428 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2429 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2430 ptfd
->funcdesc
.oVft
= (pFuncRec
->VtableOffset
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
2431 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2433 /* nameoffset is sometimes -1 on the second half of a propget/propput
2434 * pair of functions */
2435 if ((nameoffset
== -1) && (i
> 0) &&
2436 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2437 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2438 ptfd
->Name
= ptfd_prev
->Name
;
2440 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2444 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2446 /* do the parameters/arguments */
2447 if(pFuncRec
->nrargs
)
2450 MSFT_ParameterInfo paraminfo
;
2452 ptfd
->funcdesc
.lprgelemdescParam
=
2453 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2455 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2457 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2458 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2460 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2462 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2468 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2471 if (paraminfo
.oName
!= -1)
2472 ptfd
->pParamDesc
[j
].Name
=
2473 MSFT_ReadName( pcx
, paraminfo
.oName
);
2474 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2477 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2478 (pFuncRec
->FKCCIC
& 0x1000) )
2480 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2482 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2484 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2486 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2487 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2489 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2493 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2496 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2497 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2498 pFuncRec
->FKCCIC
& 0x80 )
2501 pFuncRec
->oArgCustData
[j
],
2502 &ptfd
->pParamDesc
[j
].custdata_list
);
2505 /* SEEK value = jump to offset,
2506 * from there jump to the end of record,
2507 * go back by (j-1) arguments
2509 MSFT_ReadLEDWords( ¶minfo
,
2510 sizeof(MSFT_ParameterInfo
), pcx
,
2511 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2512 * sizeof(MSFT_ParameterInfo
)));
2516 /* scode is not used: archaic win16 stuff FIXME: right? */
2517 ptfd
->funcdesc
.cScodes
= 0 ;
2518 ptfd
->funcdesc
.lprgscode
= NULL
;
2522 recoffset
+= reclength
;
2527 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2528 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2530 int infolen
, nameoffset
, reclength
;
2532 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2537 TRACE_(typelib
)("\n");
2539 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2540 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2541 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2542 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2543 recoffset
+= offset
+sizeof(INT
);
2544 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2545 /* name, eventually add to a hash table */
2546 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2547 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2548 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2549 /* read the variable information record */
2550 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2552 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2555 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2556 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2558 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2559 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2561 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2562 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2564 /* fill the VarDesc Structure */
2565 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2566 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2567 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2568 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2569 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2570 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2571 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2572 if(pVarRec
->VarKind
== VAR_CONST
){
2573 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2574 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2575 pVarRec
->OffsValue
, pcx
);
2577 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2578 recoffset
+= reclength
;
2582 /* process Implemented Interfaces of a com class */
2583 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2587 MSFT_RefRecord refrec
;
2590 TRACE_(typelib
)("\n");
2592 pTI
->impltypes
= TLBImplType_Alloc(count
);
2593 pImpl
= pTI
->impltypes
;
2594 for(i
=0;i
<count
;i
++){
2595 if(offset
<0) break; /* paranoia */
2596 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2597 pImpl
->hRef
= refrec
.reftype
;
2598 pImpl
->implflags
=refrec
.flags
;
2599 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2600 offset
=refrec
.onext
;
2606 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2607 * and some structures, and fix the alignment */
2608 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2610 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2611 switch(info
->tdescAlias
->vt
){
2619 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2620 info
->typeattr
.cbAlignment
= sizeof(void*);
2623 case VT_USERDEFINED
:
2624 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2627 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2628 info
->typeattr
.cbAlignment
= 8;
2630 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2631 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2633 info
->typeattr
.cbAlignment
= sizeof(void*);
2636 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2637 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2638 info
->typeattr
.typekind
== TKIND_COCLASS
){
2639 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2640 info
->typeattr
.cbAlignment
= sizeof(void*);
2646 * process a typeinfo record
2648 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2651 ITypeLibImpl
* pLibInfo
)
2653 MSFT_TypeInfoBase tiBase
;
2654 ITypeInfoImpl
*ptiRet
;
2656 TRACE_(typelib
)("count=%u\n", count
);
2658 ptiRet
= ITypeInfoImpl_Constructor();
2659 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2660 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2662 /* this is where we are coming from */
2663 ptiRet
->pTypeLib
= pLibInfo
;
2664 ptiRet
->index
=count
;
2666 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2667 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2668 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2669 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2670 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2671 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2672 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2673 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2674 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2675 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2676 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2677 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2678 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
;
2679 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2681 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2682 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2683 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2687 /* IDLDESC idldescType; *//* never saw this one != zero */
2689 /* name, eventually add to a hash table */
2690 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2691 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2692 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2694 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2695 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2696 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2698 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2699 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2701 /* note: InfoType's Help file and HelpStringDll come from the containing
2702 * library. Further HelpString and Docstring appear to be the same thing :(
2705 if(ptiRet
->typeattr
.cFuncs
>0 )
2706 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2707 ptiRet
->typeattr
.cVars
,
2708 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2710 if(ptiRet
->typeattr
.cVars
>0 )
2711 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2712 ptiRet
->typeattr
.cVars
,
2713 tiBase
.memoffset
, &ptiRet
->vardescs
);
2714 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2715 switch(ptiRet
->typeattr
.typekind
)
2718 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2721 case TKIND_DISPATCH
:
2722 /* This is not -1 when the interface is a non-base dual interface or
2723 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2724 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2728 if (tiBase
.datatype1
!= -1)
2730 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2731 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2735 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2736 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2740 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2742 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2743 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2744 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2745 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2746 if (TRACE_ON(typelib
))
2747 dump_TypeInfo(ptiRet
);
2752 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2755 INT16 len_str
, len_piece
;
2756 int offs
= 0, lengthInChars
;
2758 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2762 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2765 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2766 len_piece
= len_str
+ sizeof(INT16
);
2768 len_piece
= (len_piece
+ 4) & ~0x3;
2772 string
= heap_alloc(len_piece
+ 1);
2773 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2774 string
[len_str
] = '\0';
2776 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2777 string
, -1, NULL
, 0);
2778 if (!lengthInChars
) {
2780 return E_UNEXPECTED
;
2783 tlbstr
= heap_alloc(sizeof(TLBString
));
2785 tlbstr
->offset
= offs
;
2786 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2787 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2791 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2797 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2802 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2803 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2804 MSFT_ImpInfo impinfo
;
2807 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2809 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2810 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2812 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2813 if(pImpLib
->offset
==impinfo
.oImpFile
)
2816 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2817 ref
->reference
= offs
;
2818 ref
->pImpTLInfo
= pImpLib
;
2819 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2820 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2821 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2822 ref
->index
= TLB_REF_USE_GUID
;
2824 ref
->index
= impinfo
.oGuid
;
2826 ERR("Cannot find a reference\n");
2827 ref
->reference
= -1;
2828 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2831 offs
+= sizeof(impinfo
);
2837 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2838 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2839 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2842 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2843 static CRITICAL_SECTION cache_section
;
2844 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2846 0, 0, &cache_section
,
2847 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2848 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2850 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2853 typedef struct TLB_PEFile
2855 IUnknown IUnknown_iface
;
2858 HRSRC typelib_resource
;
2859 HGLOBAL typelib_global
;
2860 LPVOID typelib_base
;
2863 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2865 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2868 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2870 if (IsEqualIID(riid
, &IID_IUnknown
))
2873 IUnknown_AddRef(iface
);
2877 return E_NOINTERFACE
;
2880 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2882 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2883 return InterlockedIncrement(&This
->refs
);
2886 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2888 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2889 ULONG refs
= InterlockedDecrement(&This
->refs
);
2892 if (This
->typelib_global
)
2893 FreeResource(This
->typelib_global
);
2895 FreeLibrary(This
->dll
);
2901 static const IUnknownVtbl TLB_PEFile_Vtable
=
2903 TLB_PEFile_QueryInterface
,
2908 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2911 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2913 This
= heap_alloc(sizeof(TLB_PEFile
));
2915 return E_OUTOFMEMORY
;
2917 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2920 This
->typelib_resource
= NULL
;
2921 This
->typelib_global
= NULL
;
2922 This
->typelib_base
= NULL
;
2924 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2925 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2929 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2930 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2931 if (This
->typelib_resource
)
2933 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2934 if (This
->typelib_global
)
2936 This
->typelib_base
= LockResource(This
->typelib_global
);
2938 if (This
->typelib_base
)
2940 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2941 *ppBase
= This
->typelib_base
;
2942 *ppFile
= &This
->IUnknown_iface
;
2948 TRACE("No TYPELIB resource found\n");
2952 TLB_PEFile_Release(&This
->IUnknown_iface
);
2956 typedef struct TLB_NEFile
2958 IUnknown IUnknown_iface
;
2960 LPVOID typelib_base
;
2963 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2965 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2968 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2970 if (IsEqualIID(riid
, &IID_IUnknown
))
2973 IUnknown_AddRef(iface
);
2977 return E_NOINTERFACE
;
2980 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2982 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2983 return InterlockedIncrement(&This
->refs
);
2986 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2988 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2989 ULONG refs
= InterlockedDecrement(&This
->refs
);
2992 heap_free(This
->typelib_base
);
2998 static const IUnknownVtbl TLB_NEFile_Vtable
=
3000 TLB_NEFile_QueryInterface
,
3005 /***********************************************************************
3006 * read_xx_header [internal]
3008 static int read_xx_header( HFILE lzfd
)
3010 IMAGE_DOS_HEADER mzh
;
3013 LZSeek( lzfd
, 0, SEEK_SET
);
3014 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3016 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3019 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3020 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3023 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3025 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3026 return IMAGE_OS2_SIGNATURE
;
3027 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3028 return IMAGE_NT_SIGNATURE
;
3031 WARN("Can't handle %s files.\n", magic
);
3036 /***********************************************************************
3037 * find_ne_resource [internal]
3039 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3040 DWORD
*resLen
, DWORD
*resOff
)
3042 IMAGE_OS2_HEADER nehd
;
3043 NE_TYPEINFO
*typeInfo
;
3044 NE_NAMEINFO
*nameInfo
;
3050 /* Read in NE header */
3051 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3052 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3054 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3057 TRACE("No resources in NE dll\n" );
3061 /* Read in resource table */
3062 resTab
= heap_alloc( resTabSize
);
3063 if ( !resTab
) return FALSE
;
3065 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3066 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3068 heap_free( resTab
);
3073 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3075 if (!IS_INTRESOURCE(typeid)) /* named type */
3077 BYTE len
= strlen( typeid );
3078 while (typeInfo
->type_id
)
3080 if (!(typeInfo
->type_id
& 0x8000))
3082 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3083 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
3085 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3086 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3089 else /* numeric type id */
3091 WORD id
= LOWORD(typeid) | 0x8000;
3092 while (typeInfo
->type_id
)
3094 if (typeInfo
->type_id
== id
) goto found_type
;
3095 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3096 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3099 TRACE("No typeid entry found for %p\n", typeid );
3100 heap_free( resTab
);
3104 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3106 if (!IS_INTRESOURCE(resid
)) /* named resource */
3108 BYTE len
= strlen( resid
);
3109 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3111 BYTE
*p
= resTab
+ nameInfo
->id
;
3112 if (nameInfo
->id
& 0x8000) continue;
3113 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3116 else /* numeric resource id */
3118 WORD id
= LOWORD(resid
) | 0x8000;
3119 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3120 if (nameInfo
->id
== id
) goto found_name
;
3122 TRACE("No resid entry found for %p\n", typeid );
3123 heap_free( resTab
);
3127 /* Return resource data */
3128 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3129 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3131 heap_free( resTab
);
3135 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3139 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3142 This
= heap_alloc(sizeof(TLB_NEFile
));
3143 if (!This
) return E_OUTOFMEMORY
;
3145 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3147 This
->typelib_base
= NULL
;
3149 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3150 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3152 DWORD reslen
, offset
;
3153 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3155 This
->typelib_base
= heap_alloc(reslen
);
3156 if( !This
->typelib_base
)
3160 LZSeek( lzfd
, offset
, SEEK_SET
);
3161 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3163 *ppBase
= This
->typelib_base
;
3164 *pdwTLBLength
= reslen
;
3165 *ppFile
= &This
->IUnknown_iface
;
3171 if( lzfd
>= 0) LZClose( lzfd
);
3172 TLB_NEFile_Release(&This
->IUnknown_iface
);
3176 typedef struct TLB_Mapping
3178 IUnknown IUnknown_iface
;
3182 LPVOID typelib_base
;
3185 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3187 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3190 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3192 if (IsEqualIID(riid
, &IID_IUnknown
))
3195 IUnknown_AddRef(iface
);
3199 return E_NOINTERFACE
;
3202 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3204 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3205 return InterlockedIncrement(&This
->refs
);
3208 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3210 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3211 ULONG refs
= InterlockedDecrement(&This
->refs
);
3214 if (This
->typelib_base
)
3215 UnmapViewOfFile(This
->typelib_base
);
3217 CloseHandle(This
->mapping
);
3218 if (This
->file
!= INVALID_HANDLE_VALUE
)
3219 CloseHandle(This
->file
);
3225 static const IUnknownVtbl TLB_Mapping_Vtable
=
3227 TLB_Mapping_QueryInterface
,
3232 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3236 This
= heap_alloc(sizeof(TLB_Mapping
));
3238 return E_OUTOFMEMORY
;
3240 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3242 This
->file
= INVALID_HANDLE_VALUE
;
3243 This
->mapping
= NULL
;
3244 This
->typelib_base
= NULL
;
3246 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3247 if (INVALID_HANDLE_VALUE
!= This
->file
)
3249 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3252 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3253 if(This
->typelib_base
)
3255 /* retrieve file size */
3256 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3257 *ppBase
= This
->typelib_base
;
3258 *ppFile
= &This
->IUnknown_iface
;
3264 IUnknown_Release(&This
->IUnknown_iface
);
3265 return TYPE_E_CANTLOADLIBRARY
;
3268 /****************************************************************************
3271 * find the type of the typelib file and map the typelib resource into
3275 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3276 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3278 ITypeLibImpl
*entry
;
3281 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3282 LPVOID pBase
= NULL
;
3283 DWORD dwTLBLength
= 0;
3284 IUnknown
*pFile
= NULL
;
3289 index_str
= strrchrW(pszFileName
, '\\');
3290 if(index_str
&& *++index_str
!= '\0')
3293 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3294 if(*end_ptr
== '\0')
3296 int str_len
= index_str
- pszFileName
- 1;
3298 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3299 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3304 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3306 if(strchrW(file
, '\\'))
3308 lstrcpyW(pszPath
, file
);
3312 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3313 pszPath
[len
] = '\\';
3314 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3318 if(file
!= pszFileName
) heap_free(file
);
3320 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3321 if(h
!= INVALID_HANDLE_VALUE
){
3322 FILE_NAME_INFORMATION size_info
;
3325 /* GetFileInformationByHandleEx returns the path of the file without
3326 * WOW64 redirection */
3327 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, &size_info
, sizeof(size_info
));
3328 if(br
|| GetLastError() == ERROR_MORE_DATA
){
3329 FILE_NAME_INFORMATION
*info
;
3330 DWORD size
= sizeof(*info
) + size_info
.FileNameLength
+ sizeof(WCHAR
);
3332 info
= HeapAlloc(GetProcessHeap(), 0, size
);
3334 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, info
, size
);
3336 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3337 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3340 HeapFree(GetProcessHeap(), 0, info
);
3346 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3348 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3349 EnterCriticalSection(&cache_section
);
3350 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3352 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3354 TRACE("cache hit\n");
3355 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3356 ITypeLib2_AddRef(*ppTypeLib
);
3357 LeaveCriticalSection(&cache_section
);
3361 LeaveCriticalSection(&cache_section
);
3363 /* now actually load and parse the typelib */
3365 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3366 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3367 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3368 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3369 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3372 if (dwTLBLength
>= 4)
3374 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3375 if (dwSignature
== MSFT_SIGNATURE
)
3376 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3377 else if (dwSignature
== SLTG_SIGNATURE
)
3378 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3381 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3382 ret
= TYPE_E_CANTLOADLIBRARY
;
3386 ret
= TYPE_E_CANTLOADLIBRARY
;
3387 IUnknown_Release(pFile
);
3391 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3393 TRACE("adding to cache\n");
3394 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3395 lstrcpyW(impl
->path
, pszPath
);
3396 /* We should really canonicalise the path here. */
3397 impl
->index
= index
;
3399 /* FIXME: check if it has added already in the meantime */
3400 EnterCriticalSection(&cache_section
);
3401 list_add_head(&tlb_cache
, &impl
->entry
);
3402 LeaveCriticalSection(&cache_section
);
3408 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3410 ret
= TYPE_E_CANTLOADLIBRARY
;
3417 /*================== ITypeLib(2) Methods ===================================*/
3419 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3421 ITypeLibImpl
* pTypeLibImpl
;
3423 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3424 if (!pTypeLibImpl
) return NULL
;
3426 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3427 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3428 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3429 pTypeLibImpl
->ref
= 1;
3431 list_init(&pTypeLibImpl
->implib_list
);
3432 list_init(&pTypeLibImpl
->custdata_list
);
3433 list_init(&pTypeLibImpl
->name_list
);
3434 list_init(&pTypeLibImpl
->string_list
);
3435 list_init(&pTypeLibImpl
->guid_list
);
3436 list_init(&pTypeLibImpl
->ref_list
);
3437 pTypeLibImpl
->dispatch_href
= -1;
3439 return pTypeLibImpl
;
3442 /****************************************************************************
3443 * ITypeLib2_Constructor_MSFT
3445 * loading an MSFT typelib from an in-memory image
3447 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3451 MSFT_Header tlbHeader
;
3452 MSFT_SegDir tlbSegDir
;
3453 ITypeLibImpl
* pTypeLibImpl
;
3456 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3458 pTypeLibImpl
= TypeLibImpl_Constructor();
3459 if (!pTypeLibImpl
) return NULL
;
3461 /* get pointer to beginning of typelib data */
3465 cx
.pLibInfo
= pTypeLibImpl
;
3466 cx
.length
= dwTLBLength
;
3469 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3470 TRACE_(typelib
)("header:\n");
3471 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3472 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3473 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3476 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3478 /* there is a small amount of information here until the next important
3480 * the segment directory . Try to calculate the amount of data */
3481 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3483 /* now read the segment directory */
3484 TRACE("read segment directory (at %d)\n",lPSegDir
);
3485 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3486 cx
.pTblDir
= &tlbSegDir
;
3488 /* just check two entries */
3489 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3491 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3492 heap_free(pTypeLibImpl
);
3496 MSFT_ReadAllNames(&cx
);
3497 MSFT_ReadAllStrings(&cx
);
3498 MSFT_ReadAllGuids(&cx
);
3500 /* now fill our internal data */
3501 /* TLIBATTR fields */
3502 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3504 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3505 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3506 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3507 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3508 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3510 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3511 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3513 /* name, eventually add to a hash table */
3514 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3517 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3518 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3520 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3523 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3524 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3527 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3530 if(tlbHeader
.CustomDataOffset
>= 0)
3532 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3535 /* fill in type descriptions */
3536 if(tlbSegDir
.pTypdescTab
.length
> 0)
3538 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3540 pTypeLibImpl
->ctTypeDesc
= cTD
;
3541 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3542 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3545 /* FIXME: add several sanity checks here */
3546 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3547 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3549 /* FIXME: check safearray */
3551 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3553 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3555 else if(td
[0] == VT_CARRAY
)
3557 /* array descr table here */
3558 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3560 else if(td
[0] == VT_USERDEFINED
)
3562 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3564 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3567 /* second time around to fill the array subscript info */
3570 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3571 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3573 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3574 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3577 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3579 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3581 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3583 for(j
= 0; j
<td
[2]; j
++)
3585 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3586 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3587 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3588 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3593 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3594 ERR("didn't find array description data\n");
3599 /* imported type libs */
3600 if(tlbSegDir
.pImpFiles
.offset
>0)
3603 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3606 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3610 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3611 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3612 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3614 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3615 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3616 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3617 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3620 name
= heap_alloc_zero(size
+1);
3621 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3622 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3625 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3626 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3628 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3632 MSFT_ReadAllRefs(&cx
);
3634 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3637 if(tlbHeader
.nrtypeinfos
>= 0 )
3639 ITypeInfoImpl
**ppTI
;
3641 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3643 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3645 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3648 (pTypeLibImpl
->TypeInfoCount
)++;
3653 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3654 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3655 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3659 TRACE("(%p)\n", pTypeLibImpl
);
3660 return &pTypeLibImpl
->ITypeLib2_iface
;
3664 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3670 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3671 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3675 guid
->Data4
[0] = s
>> 8;
3676 guid
->Data4
[1] = s
& 0xff;
3679 for(i
= 0; i
< 6; i
++) {
3680 memcpy(b
, str
+ 24 + 2 * i
, 2);
3681 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3686 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3693 bytelen
= *(const WORD
*)ptr
;
3694 if(bytelen
== 0xffff) return 2;
3696 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3697 tmp_str
= SysAllocStringLen(NULL
, len
);
3699 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3700 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3701 SysFreeString(tmp_str
);
3706 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3711 bytelen
= *(const WORD
*)ptr
;
3712 if(bytelen
== 0xffff) return 2;
3713 *str
= heap_alloc(bytelen
+ 1);
3714 memcpy(*str
, ptr
+ 2, bytelen
);
3715 (*str
)[bytelen
] = '\0';
3719 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3724 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3725 if (tlbstr
->offset
== offset
)
3729 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3730 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3731 SysFreeString(tmp_str
);
3736 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3738 char *ptr
= pLibBlk
;
3741 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3742 FIXME("libblk magic = %04x\n", w
);
3747 if((w
= *(WORD
*)ptr
) != 0xffff) {
3748 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3753 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3755 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3757 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3760 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3761 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3764 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3765 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3767 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3770 ptr
+= 4; /* skip res12 */
3772 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3775 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3778 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3781 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3782 ptr
+= sizeof(GUID
);
3784 return ptr
- (char*)pLibBlk
;
3787 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3792 } sltg_ref_lookup_t
;
3794 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3795 HREFTYPE
*typelib_ref
)
3797 if(table
&& typeinfo_ref
< table
->num
)
3799 *typelib_ref
= table
->refs
[typeinfo_ref
];
3803 ERR_(typelib
)("Unable to find reference\n");
3808 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3813 if((*pType
& 0xe00) == 0xe00) {
3815 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3816 pTD
= pTD
->u
.lptdesc
;
3818 switch(*pType
& 0x3f) {
3821 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3822 pTD
= pTD
->u
.lptdesc
;
3825 case VT_USERDEFINED
:
3826 pTD
->vt
= VT_USERDEFINED
;
3827 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3833 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3836 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3838 pTD
->vt
= VT_CARRAY
;
3839 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3840 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3841 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3842 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3844 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3850 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3854 pTD
->vt
= VT_SAFEARRAY
;
3855 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3856 pTD
= pTD
->u
.lptdesc
;
3860 pTD
->vt
= *pType
& 0x3f;
3869 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3870 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3872 /* Handle [in/out] first */
3873 if((*pType
& 0xc000) == 0xc000)
3874 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3875 else if(*pType
& 0x8000)
3876 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3877 else if(*pType
& 0x4000)
3878 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3880 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3883 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3886 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3888 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3892 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3897 TLBRefType
*ref_type
;
3898 sltg_ref_lookup_t
*table
;
3899 HREFTYPE typelib_ref
;
3901 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3902 FIXME("Ref magic = %x\n", pRef
->magic
);
3905 name
= ( (char*)pRef
->names
+ pRef
->number
);
3907 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3908 table
->num
= pRef
->number
>> 3;
3910 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3912 /* We don't want the first href to be 0 */
3913 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3915 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3917 unsigned int lib_offs
, type_num
;
3919 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3921 name
+= SLTG_ReadStringA(name
, &refname
);
3922 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3923 FIXME_(typelib
)("Can't sscanf ref\n");
3924 if(lib_offs
!= 0xffff) {
3927 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3928 if(import
->offset
== lib_offs
)
3931 if(&import
->entry
== &pTL
->implib_list
) {
3932 char fname
[MAX_PATH
+1];
3936 import
= heap_alloc_zero(sizeof(*import
));
3937 import
->offset
= lib_offs
;
3938 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3939 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3940 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3941 &import
->wVersionMajor
,
3942 &import
->wVersionMinor
,
3943 &import
->lcid
, fname
) != 4) {
3944 FIXME_(typelib
)("can't sscanf ref %s\n",
3945 pNameTable
+ lib_offs
+ 40);
3947 len
= strlen(fname
);
3948 if(fname
[len
-1] != '#')
3949 FIXME("fname = %s\n", fname
);
3950 fname
[len
-1] = '\0';
3951 import
->name
= TLB_MultiByteToBSTR(fname
);
3952 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3954 ref_type
->pImpTLInfo
= import
;
3956 /* Store a reference to IDispatch */
3957 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3958 pTL
->dispatch_href
= typelib_ref
;
3960 } else { /* internal ref */
3961 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3963 ref_type
->reference
= typelib_ref
;
3964 ref_type
->index
= type_num
;
3967 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3969 table
->refs
[ref
] = typelib_ref
;
3972 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3973 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3974 dump_TLBRefType(pTL
);
3978 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3979 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3981 SLTG_ImplInfo
*info
;
3982 TLBImplType
*pImplType
;
3983 /* I don't really get this structure, usually it's 0x16 bytes
3984 long, but iuser.tlb contains some that are 0x18 bytes long.
3985 That's ok because we can use the next ptr to jump to the next
3986 one. But how do we know the length of the last one? The WORD
3987 at offs 0x8 might be the clue. For now I'm just assuming that
3988 the last one is the regular 0x16 bytes. */
3990 info
= (SLTG_ImplInfo
*)pBlk
;
3992 pTI
->typeattr
.cImplTypes
++;
3993 if(info
->next
== 0xffff)
3995 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3998 info
= (SLTG_ImplInfo
*)pBlk
;
3999 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
4000 pImplType
= pTI
->impltypes
;
4002 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4003 pImplType
->implflags
= info
->impltypeflags
;
4006 if(info
->next
== 0xffff)
4009 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4010 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4012 info
++; /* see comment at top of function */
4016 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4017 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4019 TLBVarDesc
*pVarDesc
;
4020 const TLBString
*prevName
= NULL
;
4021 SLTG_Variable
*pItem
;
4025 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4027 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4028 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4030 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4032 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4033 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4034 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4038 if (pItem
->name
== 0xfffe)
4039 pVarDesc
->Name
= prevName
;
4041 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4043 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4044 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4045 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4047 if(pItem
->flags
& 0x02)
4048 pType
= &pItem
->type
;
4050 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4052 if (pItem
->flags
& ~0xda)
4053 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4055 SLTG_DoElem(pType
, pBlk
,
4056 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4058 if (TRACE_ON(typelib
)) {
4060 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4061 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4064 if (pItem
->flags
& 0x40) {
4065 TRACE_(typelib
)("VAR_DISPATCH\n");
4066 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4068 else if (pItem
->flags
& 0x10) {
4069 TRACE_(typelib
)("VAR_CONST\n");
4070 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4071 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4072 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4073 if (pItem
->flags
& 0x08)
4074 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4076 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4082 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4084 TRACE_(typelib
)("len = %u\n", len
);
4085 if (len
== 0xffff) {
4088 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4089 str
= SysAllocStringLen(NULL
, alloc_len
);
4090 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4092 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4093 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4102 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4103 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4106 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4111 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4112 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4113 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4116 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4117 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4119 if (pItem
->flags
& 0x80)
4120 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4122 prevName
= pVarDesc
->Name
;
4124 pTI
->typeattr
.cVars
= cVars
;
4127 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4128 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4130 SLTG_Function
*pFunc
;
4132 TLBFuncDesc
*pFuncDesc
;
4134 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4136 pFuncDesc
= pTI
->funcdescs
;
4137 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4138 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4143 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4144 case SLTG_FUNCTION_MAGIC
:
4145 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4147 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4148 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4150 case SLTG_STATIC_FUNCTION_MAGIC
:
4151 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4154 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4157 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4159 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4160 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4161 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4162 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4163 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4164 pFuncDesc
->funcdesc
.oVft
= (pFunc
->vtblpos
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
4166 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4167 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4169 if(pFunc
->retnextopt
& 0x80)
4170 pType
= &pFunc
->rettype
;
4172 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4174 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4176 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4177 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4178 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4180 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4182 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4183 char *paramName
= pNameTable
+ *pArg
;
4185 /* If arg type follows then paramName points to the 2nd
4186 letter of the name, else the next WORD is an offset to
4187 the arg type and paramName points to the first letter.
4188 So let's take one char off paramName and see if we're
4189 pointing at an alpha-numeric char. However if *pArg is
4190 0xffff or 0xfffe then the param has no name, the former
4191 meaning that the next WORD is the type, the latter
4192 meaning that the next WORD is an offset to the type. */
4197 else if(*pArg
== 0xfffe) {
4201 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4206 if(HaveOffs
) { /* the next word is an offset to type */
4207 pType
= (WORD
*)(pBlk
+ *pArg
);
4208 SLTG_DoElem(pType
, pBlk
,
4209 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4214 pArg
= SLTG_DoElem(pArg
, pBlk
,
4215 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4218 /* Are we an optional param ? */
4219 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4220 pFuncDesc
->funcdesc
.cParamsOpt
)
4221 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4224 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4225 paramName
- pNameTable
, pTI
->pTypeLib
);
4227 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4231 pTI
->typeattr
.cFuncs
= cFuncs
;
4234 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4235 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4236 SLTG_TypeInfoTail
*pTITail
)
4239 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4241 if(pTIHeader
->href_table
!= 0xffffffff) {
4242 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4248 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4249 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4251 heap_free(ref_lookup
);
4255 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4256 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4257 const SLTG_TypeInfoTail
*pTITail
)
4260 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4262 if(pTIHeader
->href_table
!= 0xffffffff) {
4263 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4269 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4270 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4273 if (pTITail
->funcs_off
!= 0xffff)
4274 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4276 heap_free(ref_lookup
);
4278 if (TRACE_ON(typelib
))
4279 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4282 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4283 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4284 const SLTG_TypeInfoTail
*pTITail
)
4286 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4289 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4290 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4291 const SLTG_TypeInfoTail
*pTITail
)
4294 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4296 if (pTITail
->simple_alias
) {
4297 /* if simple alias, no more processing required */
4298 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4299 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4303 if(pTIHeader
->href_table
!= 0xffffffff) {
4304 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4308 /* otherwise it is an offset to a type */
4309 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4311 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4312 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4314 heap_free(ref_lookup
);
4317 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4318 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4319 const SLTG_TypeInfoTail
*pTITail
)
4321 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4322 if (pTIHeader
->href_table
!= 0xffffffff)
4323 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4326 if (pTITail
->vars_off
!= 0xffff)
4327 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4329 if (pTITail
->funcs_off
!= 0xffff)
4330 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4332 if (pTITail
->impls_off
!= 0xffff)
4333 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4335 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4336 * of dispinterface functions including the IDispatch ones, so
4337 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4338 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4340 heap_free(ref_lookup
);
4341 if (TRACE_ON(typelib
))
4342 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4345 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4346 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4347 const SLTG_TypeInfoTail
*pTITail
)
4349 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4352 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4353 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4354 const SLTG_TypeInfoTail
*pTITail
)
4356 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4357 if (pTIHeader
->href_table
!= 0xffffffff)
4358 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4361 if (pTITail
->vars_off
!= 0xffff)
4362 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4364 if (pTITail
->funcs_off
!= 0xffff)
4365 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4366 heap_free(ref_lookup
);
4367 if (TRACE_ON(typelib
))
4371 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4372 manageable copy of it into this */
4385 } SLTG_InternalOtherTypeInfo
;
4387 /****************************************************************************
4388 * ITypeLib2_Constructor_SLTG
4390 * loading a SLTG typelib from an in-memory image
4392 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4394 ITypeLibImpl
*pTypeLibImpl
;
4395 SLTG_Header
*pHeader
;
4396 SLTG_BlkEntry
*pBlkEntry
;
4400 LPVOID pBlk
, pFirstBlk
;
4401 SLTG_LibBlk
*pLibBlk
;
4402 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4403 char *pAfterOTIBlks
= NULL
;
4404 char *pNameTable
, *ptr
;
4407 ITypeInfoImpl
**ppTypeInfoImpl
;
4409 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4412 pTypeLibImpl
= TypeLibImpl_Constructor();
4413 if (!pTypeLibImpl
) return NULL
;
4417 TRACE_(typelib
)("header:\n");
4418 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4419 pHeader
->nrOfFileBlks
);
4420 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4421 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4422 pHeader
->SLTG_magic
);
4426 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4427 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4429 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4430 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4432 /* Next we have a magic block */
4433 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4435 /* Let's see if we're still in sync */
4436 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4437 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4438 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4441 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4442 sizeof(SLTG_DIR_MAGIC
))) {
4443 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4447 pIndex
= (SLTG_Index
*)(pMagic
+1);
4449 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4451 pFirstBlk
= pPad9
+ 1;
4453 /* We'll set up a ptr to the main library block, which is the last one. */
4455 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4456 pBlkEntry
[order
].next
!= 0;
4457 order
= pBlkEntry
[order
].next
- 1) {
4458 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4462 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4464 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4469 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4471 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4474 ptr
= (char*)pLibBlk
+ len
;
4476 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4480 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4482 w
= *(WORD
*)(ptr
+ 2);
4485 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4486 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4487 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4489 w
= *(WORD
*)(ptr
+ 4 + len
);
4491 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4493 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4494 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4495 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4497 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4498 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4499 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4501 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4502 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4505 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4506 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4507 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4508 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4509 len
+= sizeof(SLTG_OtherTypeInfo
);
4513 pAfterOTIBlks
= ptr
;
4515 /* Skip this WORD and get the next DWORD */
4516 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4518 /* Now add this to pLibBLk look at what we're pointing at and
4519 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4520 dust and we should be pointing at the beginning of the name
4523 pNameTable
= (char*)pLibBlk
+ len
;
4525 switch(*(WORD
*)pNameTable
) {
4532 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4536 pNameTable
+= 0x216;
4540 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4542 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4545 /* Hopefully we now have enough ptrs set up to actually read in
4546 some TypeInfos. It's not clear which order to do them in, so
4547 I'll just follow the links along the BlkEntry chain and read
4548 them in the order in which they are in the file */
4550 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4551 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4553 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4554 pBlkEntry
[order
].next
!= 0;
4555 order
= pBlkEntry
[order
].next
- 1, i
++) {
4557 SLTG_TypeInfoHeader
*pTIHeader
;
4558 SLTG_TypeInfoTail
*pTITail
;
4559 SLTG_MemberHeader
*pMemHeader
;
4561 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4562 FIXME_(typelib
)("Index strings don't match\n");
4563 heap_free(pOtherTypeInfoBlks
);
4568 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4569 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4570 heap_free(pOtherTypeInfoBlks
);
4573 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4574 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4575 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4577 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4578 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4579 (*ppTypeInfoImpl
)->index
= i
;
4580 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4581 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4582 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4583 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4584 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4585 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4586 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4587 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4589 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4590 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4592 if((pTIHeader
->typeflags1
& 7) != 2)
4593 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4594 if(pTIHeader
->typeflags3
!= 2)
4595 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4597 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4598 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4599 typekind_desc
[pTIHeader
->typekind
],
4600 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4601 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4603 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4605 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4607 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4608 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4609 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4611 switch(pTIHeader
->typekind
) {
4613 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4614 pTIHeader
, pTITail
);
4618 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4619 pTIHeader
, pTITail
);
4622 case TKIND_INTERFACE
:
4623 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4624 pTIHeader
, pTITail
);
4628 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4629 pTIHeader
, pTITail
);
4633 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4634 pTIHeader
, pTITail
);
4637 case TKIND_DISPATCH
:
4638 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4639 pTIHeader
, pTITail
);
4643 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4644 pTIHeader
, pTITail
);
4648 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4653 /* could get cFuncs, cVars and cImplTypes from here
4654 but we've already set those */
4655 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4671 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4674 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4675 FIXME("Somehow processed %d TypeInfos\n", i
);
4676 heap_free(pOtherTypeInfoBlks
);
4680 heap_free(pOtherTypeInfoBlks
);
4681 return &pTypeLibImpl
->ITypeLib2_iface
;
4684 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4686 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4688 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4690 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4691 IsEqualIID(riid
,&IID_ITypeLib
)||
4692 IsEqualIID(riid
,&IID_ITypeLib2
))
4694 *ppv
= &This
->ITypeLib2_iface
;
4696 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4697 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4699 *ppv
= &This
->ICreateTypeLib2_iface
;
4704 TRACE("-- Interface: E_NOINTERFACE\n");
4705 return E_NOINTERFACE
;
4708 IUnknown_AddRef((IUnknown
*)*ppv
);
4712 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4714 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4715 ULONG ref
= InterlockedIncrement(&This
->ref
);
4717 TRACE("(%p) ref=%u\n", This
, ref
);
4722 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4724 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4725 ULONG ref
= InterlockedDecrement(&This
->ref
);
4727 TRACE("(%p) ref=%u\n",This
, ref
);
4731 TLBImpLib
*pImpLib
, *pImpLibNext
;
4732 TLBRefType
*ref_type
, *ref_type_next
;
4733 TLBString
*tlbstr
, *tlbstr_next
;
4734 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
, ref_type_next
, &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 extern double call_double_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6311 __ASM_GLOBAL_FUNC( call_method
,
6313 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6314 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6315 "movl %esp,%ebp\n\t"
6316 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6318 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6320 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6321 "movl 12(%ebp),%edx\n\t"
6322 "movl %esp,%edi\n\t"
6325 "subl %edx,%edi\n\t"
6326 "andl $~15,%edi\n\t"
6327 "movl %edi,%esp\n\t"
6328 "movl 12(%ebp),%ecx\n\t"
6329 "movl 16(%ebp),%esi\n\t"
6332 "1:\tcall *8(%ebp)\n\t"
6333 "subl %esp,%edi\n\t"
6334 "movl 20(%ebp),%ecx\n\t"
6335 "movl %edi,(%ecx)\n\t"
6336 "leal -8(%ebp),%esp\n\t"
6338 __ASM_CFI(".cfi_same_value %edi\n\t")
6340 __ASM_CFI(".cfi_same_value %esi\n\t")
6342 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6343 __ASM_CFI(".cfi_same_value %ebp\n\t")
6345 __ASM_GLOBAL_FUNC( call_double_method
,
6346 "jmp " __ASM_NAME("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 extern double CDECL
call_double_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6384 __ASM_GLOBAL_FUNC( call_method
,
6386 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6387 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6388 "movq %rsp,%rbp\n\t"
6389 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6391 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6393 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6394 "movq %rcx,%rax\n\t"
6397 "cmovgq %rdx,%rcx\n\t"
6398 "leaq 0(,%rcx,8),%rdx\n\t"
6399 "subq %rdx,%rsp\n\t"
6400 "andq $~15,%rsp\n\t"
6401 "movq %rsp,%rdi\n\t"
6404 "movq 0(%rsp),%rcx\n\t"
6405 "movq 8(%rsp),%rdx\n\t"
6406 "movq 16(%rsp),%r8\n\t"
6407 "movq 24(%rsp),%r9\n\t"
6408 "movq 0(%rsp),%xmm0\n\t"
6409 "movq 8(%rsp),%xmm1\n\t"
6410 "movq 16(%rsp),%xmm2\n\t"
6411 "movq 24(%rsp),%xmm3\n\t"
6413 "leaq -16(%rbp),%rsp\n\t"
6415 __ASM_CFI(".cfi_same_value %rdi\n\t")
6417 __ASM_CFI(".cfi_same_value %rsi\n\t")
6418 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6420 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6421 __ASM_CFI(".cfi_same_value %rbp\n\t")
6423 __ASM_GLOBAL_FUNC( call_double_method
,
6424 "jmp " __ASM_NAME("call_method") )
6426 #elif defined(__arm__)
6428 extern LONGLONG CDECL
call_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6429 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6430 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6431 __ASM_GLOBAL_FUNC( call_method
,
6434 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6435 * r3 = *reg_args (pointer to 8, 64-bit d0-d7 (double) values OR as 16, 32-bit s0-s15 (float) values, followed by 4, 32-bit (DWORD) r0-r3 values)
6438 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6439 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6441 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6442 "beq 1f\n\t" /* Skip allocation if no stack args */
6443 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6444 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6445 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6446 "subs r1, r1, #4\n\t" /* Decrement count */
6447 "bgt 2b\n\t" /* Loop till done */
6451 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6453 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6454 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6456 "blx ip\n\t" /* Call the target function */
6458 "mov sp, fp\n\t" /* Clean the stack using fp */
6459 "pop {fp, pc}\n\t" /* Restore fp and return */
6461 __ASM_GLOBAL_FUNC( call_float_method
,
6462 "b " __ASM_NAME("call_method") )
6463 __ASM_GLOBAL_FUNC( call_double_method
,
6464 "b " __ASM_NAME("call_method") )
6466 #endif /* __arm__ */
6468 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6471 ITypeInfo
*tinfo2
= NULL
;
6472 TYPEATTR
*tattr
= NULL
;
6474 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6477 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6479 tdesc
->u
.hreftype
, hr
);
6482 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6485 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6486 ITypeInfo_Release(tinfo2
);
6490 switch (tattr
->typekind
)
6497 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6500 case TKIND_INTERFACE
:
6501 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6507 case TKIND_DISPATCH
:
6516 FIXME("TKIND_RECORD unhandled.\n");
6521 FIXME("TKIND_UNION unhandled.\n");
6526 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6530 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6531 ITypeInfo_Release(tinfo2
);
6535 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6539 /* enforce only one level of pointer indirection */
6540 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6542 tdesc
= tdesc
->u
.lptdesc
;
6544 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6545 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6546 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6547 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6548 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6550 VARTYPE vt_userdefined
= 0;
6551 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6552 if (tdesc
->vt
== VT_PTR
)
6554 vt_userdefined
= VT_BYREF
;
6555 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6557 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6559 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6560 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6562 *vt
|= vt_userdefined
;
6574 case VT_USERDEFINED
:
6575 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6582 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6583 hr
= DISP_E_BADVARTYPE
;
6587 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6602 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6608 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6612 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6614 ITypeInfo_Release(tinfo2
);
6618 switch(tattr
->typekind
) {
6620 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6623 case TKIND_INTERFACE
:
6624 case TKIND_DISPATCH
:
6625 *guid
= tattr
->guid
;
6629 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6630 hres
= E_UNEXPECTED
;
6633 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6634 ITypeInfo_Release(tinfo2
);
6638 /***********************************************************************
6639 * DispCallFunc (OLEAUT32.@)
6641 * Invokes a function of the specified calling convention, passing the
6642 * specified arguments and returns the result.
6645 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6646 * oVft [I] The offset in the vtable. See notes.
6647 * cc [I] Calling convention of the function to call.
6648 * vtReturn [I] The return type of the function.
6649 * cActuals [I] Number of parameters.
6650 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6651 * prgpvarg [I] The arguments to pass.
6652 * pvargResult [O] The return value of the function. Can be NULL.
6656 * Failure: HRESULT code.
6659 * The HRESULT return value of this function is not affected by the return
6660 * value of the user supplied function, which is returned in pvargResult.
6662 * If pvInstance is NULL then a non-object function is to be called and oVft
6663 * is the address of the function to call.
6665 * The cc parameter can be one of the following values:
6678 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6679 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6682 int argspos
, stack_offset
;
6687 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6688 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6689 pvargResult
, V_VT(pvargResult
));
6691 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6693 FIXME("unsupported calling convention %d\n",cc
);
6694 return E_INVALIDARG
;
6697 /* maximum size for an argument is sizeof(VARIANT) */
6698 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6700 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6704 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6705 func
= vtable
[oVft
/sizeof(void *)];
6706 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6708 else func
= (void *)oVft
;
6710 for (i
= 0; i
< cActuals
; i
++)
6712 VARIANT
*arg
= prgpvarg
[i
];
6723 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6724 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6728 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6729 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6731 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6732 args
[argspos
++] = V_BOOL(arg
);
6735 args
[argspos
++] = V_UI4(arg
);
6738 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6744 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6747 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6751 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6755 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6756 call_method( func
, argspos
, args
, &stack_offset
);
6761 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6764 WARN("invalid return type %u\n", vtReturn
);
6766 return E_INVALIDARG
;
6768 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6772 if (stack_offset
&& cc
== CC_STDCALL
)
6774 WARN( "stack pointer off by %d\n", stack_offset
);
6775 return DISP_E_BADCALLEE
;
6777 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6778 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6781 #elif defined(__x86_64__)
6787 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6788 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6789 pvargResult
, V_VT(pvargResult
));
6791 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6793 FIXME("unsupported calling convention %d\n",cc
);
6794 return E_INVALIDARG
;
6797 /* maximum size for an argument is sizeof(DWORD_PTR) */
6798 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6800 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6804 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6805 func
= vtable
[oVft
/sizeof(void *)];
6806 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6808 else func
= (void *)oVft
;
6810 for (i
= 0; i
< cActuals
; i
++)
6812 VARIANT
*arg
= prgpvarg
[i
];
6818 args
[argspos
++] = (ULONG_PTR
)arg
;
6820 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6821 args
[argspos
++] = V_BOOL(arg
);
6824 args
[argspos
++] = V_UI8(arg
);
6827 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6833 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6837 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6841 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6842 call_method( func
, argspos
, args
);
6845 WARN("invalid return type %u\n", vtReturn
);
6847 return E_INVALIDARG
;
6849 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6853 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6854 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6857 #elif defined(__arm__)
6871 int rcount
; /* 32-bit register index count */
6873 int scount
= 0; /* single-precision float register index count */
6874 int dcount
= 0; /* double-precision float register index count */
6877 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6878 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6880 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6882 FIXME("unsupported calling convention %d\n",cc
);
6883 return E_INVALIDARG
;
6889 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6890 /* first as it will need to be in the 'r' registers: */
6895 regs
.r
[rcount
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6898 WARN("invalid return type %u\n", vtReturn
);
6899 return E_INVALIDARG
;
6900 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6906 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6907 func
= vtable
[oVft
/sizeof(void *)];
6908 regs
.r
[rcount
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6910 else func
= (void *)oVft
;
6912 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6913 args
= heap_alloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 4 );
6915 for (i
= 0; i
< cActuals
; i
++)
6917 VARIANT
*arg
= prgpvarg
[i
];
6918 DWORD
*pdwarg
= (DWORD
*)(arg
); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6919 int ntemp
; /* Used for counting words split between registers and stack */
6925 case VT_R8
: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6928 dcount
= max( (scount
+ 1) / 2, dcount
);
6931 regs
.sd
.d
[dcount
++] = V_R8(arg
);
6935 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6936 memcpy( &args
[argspos
], &V_R8(arg
), sizeof(V_R8(arg
)) );
6937 argspos
+= sizeof(V_R8(arg
)) / sizeof(DWORD
);
6941 case VT_I8
: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6946 rcount
+= (rcount
% 2); /* align rcount to 8-byte register pair */
6947 memcpy( ®s
.r
[rcount
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6948 rcount
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6952 rcount
= 4; /* Make sure we flag that all 'r' regs are full */
6953 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6954 memcpy( &args
[argspos
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6955 argspos
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6958 case VT_DECIMAL
: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6960 /* 8-byte align 'r' and/or stack: */
6962 rcount
+= (rcount
% 2);
6966 argspos
+= (argspos
% 2);
6968 ntemp
= sizeof(*arg
) / sizeof(DWORD
);
6972 regs
.r
[rcount
++] = *pdwarg
++;
6974 args
[argspos
++] = *pdwarg
++;
6978 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6980 regs
.r
[rcount
++] = V_BOOL(arg
);
6982 args
[argspos
++] = V_BOOL(arg
);
6984 case VT_R4
: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6986 if (!(scount
% 2)) scount
= max( scount
, dcount
* 2 );
6988 regs
.sd
.s
[scount
++] = V_R4(arg
);
6990 args
[argspos
++] = V_UI4(arg
);
6995 regs
.r
[rcount
++] = V_UI4(arg
);
6997 args
[argspos
++] = V_UI4(arg
);
7000 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
7003 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 8-byte */
7007 case VT_EMPTY
: /* EMPTY = no return value */
7008 case VT_DECIMAL
: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
7010 call_method( func
, argspos
, args
, (DWORD
*)®s
);
7013 V_R4(pvargResult
) = call_float_method( func
, argspos
, args
, (DWORD
*)®s
);
7017 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, (DWORD
*)®s
);
7022 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
7025 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
7029 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
7030 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
7034 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7035 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
7040 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
7042 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
7045 #define INVBUF_ELEMENT_SIZE \
7046 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7047 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7048 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7049 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7050 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7051 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7052 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7053 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7055 static HRESULT WINAPI
ITypeInfo_fnInvoke(
7060 DISPPARAMS
*pDispParams
,
7061 VARIANT
*pVarResult
,
7062 EXCEPINFO
*pExcepInfo
,
7065 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7067 unsigned int var_index
;
7070 const TLBFuncDesc
*pFuncInfo
;
7073 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7074 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
7077 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7078 return DISP_E_MEMBERNOTFOUND
;
7082 ERR("NULL pDispParams not allowed\n");
7083 return E_INVALIDARG
;
7086 dump_DispParms(pDispParams
);
7088 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7090 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7091 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7092 return E_INVALIDARG
;
7095 /* we do this instead of using GetFuncDesc since it will return a fake
7096 * FUNCDESC for dispinterfaces and we want the real function description */
7097 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7098 pFuncInfo
= &This
->funcdescs
[fdc
];
7099 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7100 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7101 !func_restricted( &pFuncInfo
->funcdesc
))
7105 if (fdc
< This
->typeattr
.cFuncs
) {
7106 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7110 TRACE("invoking:\n");
7111 dump_TLBFuncDescOne(pFuncInfo
);
7114 switch (func_desc
->funckind
) {
7115 case FUNC_PUREVIRTUAL
:
7116 case FUNC_VIRTUAL
: {
7117 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7119 VARIANT retval
; /* pointer for storing byref retvals in */
7120 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7121 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7122 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7123 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7124 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7125 UINT vargs_converted
=0;
7129 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7131 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7133 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7134 hres
= DISP_E_PARAMNOTFOUND
;
7139 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7141 ERR("functions with the vararg attribute do not support named arguments\n");
7142 hres
= DISP_E_NONAMEDARGS
;
7146 for (i
= 0; i
< func_desc
->cParams
; i
++)
7148 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7149 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7154 TRACE("changing args\n");
7155 for (i
= 0; i
< func_desc
->cParams
; i
++)
7157 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7158 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7159 VARIANTARG
*src_arg
;
7161 if (wParamFlags
& PARAMFLAG_FLCID
)
7164 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7166 V_I4(arg
) = This
->pTypeLib
->lcid
;
7175 for (j
= 0; j
< cNamedArgs
; j
++)
7176 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7178 src_arg
= &pDispParams
->rgvarg
[j
];
7183 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7185 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7189 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7191 /* under most conditions the caller is not allowed to
7192 * pass in a dispparam arg in the index of what would be
7193 * the retval parameter. however, there is an exception
7194 * where the extra parameter is used in an extra
7195 * IDispatch::Invoke below */
7196 if ((i
< pDispParams
->cArgs
) &&
7197 ((func_desc
->cParams
!= 1) || !pVarResult
||
7198 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7200 hres
= DISP_E_BADPARAMCOUNT
;
7204 /* note: this check is placed so that if the caller passes
7205 * in a VARIANTARG for the retval we just ignore it, like
7207 if (i
== func_desc
->cParams
- 1)
7210 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7211 memset(arg
, 0, sizeof(*arg
));
7212 V_VT(arg
) = rgvt
[i
];
7213 memset(&retval
, 0, sizeof(retval
));
7214 V_BYREF(arg
) = &retval
;
7218 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7219 hres
= E_UNEXPECTED
;
7225 TRACE("%s\n", debugstr_variant(src_arg
));
7227 if(rgvt
[i
]!=V_VT(src_arg
))
7229 if (rgvt
[i
] == VT_VARIANT
)
7230 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7231 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7233 if (rgvt
[i
] == V_VT(src_arg
))
7234 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7237 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7238 if (wParamFlags
& PARAMFLAG_FIN
)
7239 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7240 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7242 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7244 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7247 SAFEARRAYBOUND bound
;
7251 bound
.cElements
= pDispParams
->cArgs
-i
;
7252 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7254 ERR("SafeArrayCreate failed\n");
7257 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7260 ERR("SafeArrayAccessData failed with %x\n", hres
);
7261 SafeArrayDestroy(a
);
7264 for (j
= 0; j
< bound
.cElements
; j
++)
7265 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7266 hres
= SafeArrayUnaccessData(a
);
7269 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7270 SafeArrayDestroy(a
);
7273 if (rgvt
[i
] & VT_BYREF
)
7274 V_BYREF(&rgvarg
[i
]) = &a
;
7276 V_ARRAY(&rgvarg
[i
]) = a
;
7277 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7279 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7281 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7282 if (wParamFlags
& PARAMFLAG_FIN
)
7283 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7285 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7286 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7287 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7289 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7291 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7292 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7296 /* FIXME: this doesn't work for VT_BYREF arguments if
7297 * they are not the same type as in the paramdesc */
7298 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7299 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7300 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7305 ERR("failed to convert param %d to %s from %s\n", i
,
7306 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7309 prgpvarg
[i
] = &rgvarg
[i
];
7313 prgpvarg
[i
] = src_arg
;
7316 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7317 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7318 && V_UNKNOWN(prgpvarg
[i
])) {
7319 IUnknown
*userdefined_iface
;
7322 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7326 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7328 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7332 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7333 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7336 else if (wParamFlags
& PARAMFLAG_FOPT
)
7339 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7340 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7342 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7348 VARIANTARG
*missing_arg
;
7349 /* if the function wants a pointer to a variant then
7350 * set that up, otherwise just pass the VT_ERROR in
7351 * the argument by value */
7352 if (rgvt
[i
] & VT_BYREF
)
7354 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7355 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7356 V_VARIANTREF(arg
) = missing_arg
;
7360 V_VT(missing_arg
) = VT_ERROR
;
7361 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7366 hres
= DISP_E_BADPARAMCOUNT
;
7370 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7372 /* VT_VOID is a special case for return types, so it is not
7373 * handled in the general function */
7374 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7375 V_VT(&varresult
) = VT_EMPTY
;
7378 V_VT(&varresult
) = 0;
7379 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7380 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7383 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7384 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7385 prgpvarg
, &varresult
);
7387 vargs_converted
= 0;
7389 for (i
= 0; i
< func_desc
->cParams
; i
++)
7391 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7392 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7394 if (wParamFlags
& PARAMFLAG_FLCID
)
7396 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7398 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7402 VariantInit(pVarResult
);
7403 /* deref return value */
7404 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7407 VARIANT_ClearInd(prgpvarg
[i
]);
7409 else if (vargs_converted
< pDispParams
->cArgs
)
7411 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7412 if (wParamFlags
& PARAMFLAG_FOUT
)
7414 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7416 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7420 ERR("failed to convert param %d to vt %d\n", i
,
7421 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7426 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7427 func_desc
->cParamsOpt
< 0 &&
7428 i
== func_desc
->cParams
-1)
7430 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7433 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7436 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7439 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7442 ERR("SafeArrayAccessData failed with %x\n", hres
);
7445 for (j
= 0; j
<= ubound
; j
++)
7446 VariantClear(&v
[j
]);
7447 hres
= SafeArrayUnaccessData(a
);
7450 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7454 VariantClear(&rgvarg
[i
]);
7457 else if (wParamFlags
& PARAMFLAG_FOPT
)
7459 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7460 VariantClear(&rgvarg
[i
]);
7463 VariantClear(&missing_arg
[i
]);
7466 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7468 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7469 hres
= DISP_E_EXCEPTION
;
7472 IErrorInfo
*pErrorInfo
;
7473 pExcepInfo
->scode
= V_ERROR(&varresult
);
7474 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7476 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7477 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7478 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7479 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7481 IErrorInfo_Release(pErrorInfo
);
7485 if (V_VT(&varresult
) != VT_ERROR
)
7487 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7491 VariantClear(pVarResult
);
7492 *pVarResult
= varresult
;
7495 VariantClear(&varresult
);
7498 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7499 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7500 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7501 (pDispParams
->cArgs
!= 0))
7503 if (V_VT(pVarResult
) == VT_DISPATCH
)
7505 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7506 /* Note: not VariantClear; we still need the dispatch
7507 * pointer to be valid */
7508 VariantInit(pVarResult
);
7509 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7510 GetSystemDefaultLCID(), wFlags
,
7511 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7512 IDispatch_Release(pDispatch
);
7516 VariantClear(pVarResult
);
7517 hres
= DISP_E_NOTACOLLECTION
;
7525 case FUNC_DISPATCH
: {
7528 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7529 if (SUCCEEDED(hres
)) {
7530 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7531 hres
= IDispatch_Invoke(
7532 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7533 pVarResult
,pExcepInfo
,pArgErr
7536 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7537 IDispatch_Release(disp
);
7539 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7543 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7548 TRACE("-- 0x%08x\n", hres
);
7551 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7554 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7555 if(FAILED(hres
)) return hres
;
7557 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7558 dump_VARDESC(var_desc
);
7559 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7563 /* not found, look for it in inherited interfaces */
7564 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7565 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7566 if(This
->impltypes
) {
7567 /* recursive search */
7569 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7570 if(SUCCEEDED(hres
)){
7571 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7572 ITypeInfo_Release(pTInfo
);
7575 WARN("Could not search inherited interface!\n");
7578 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7579 return DISP_E_MEMBERNOTFOUND
;
7582 /* ITypeInfo::GetDocumentation
7584 * Retrieves the documentation string, the complete Help file name and path,
7585 * and the context ID for the Help topic for a specified type description.
7587 * (Can be tested by the Visual Basic Editor in Word for instance.)
7589 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7590 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7591 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7593 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7594 const TLBFuncDesc
*pFDesc
;
7595 const TLBVarDesc
*pVDesc
;
7596 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7597 " HelpContext(%p) HelpFile(%p)\n",
7598 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7599 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7601 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7603 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7605 *pdwHelpContext
=This
->dwHelpContext
;
7607 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7609 }else {/* for a member */
7610 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7613 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7615 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7617 *pdwHelpContext
=pFDesc
->helpcontext
;
7619 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7622 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
7625 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7627 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7629 *pdwHelpContext
=pVDesc
->HelpContext
;
7631 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7636 if(This
->impltypes
&&
7637 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7638 /* recursive search */
7641 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7642 if(SUCCEEDED(result
)) {
7643 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7644 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7645 ITypeInfo_Release(pTInfo
);
7648 WARN("Could not search inherited interface!\n");
7651 WARN("member %d not found\n", memid
);
7652 return TYPE_E_ELEMENTNOTFOUND
;
7655 /* ITypeInfo::GetDllEntry
7657 * Retrieves a description or specification of an entry point for a function
7660 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7661 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7664 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7665 const TLBFuncDesc
*pFDesc
;
7667 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7669 if (pBstrDllName
) *pBstrDllName
= NULL
;
7670 if (pBstrName
) *pBstrName
= NULL
;
7671 if (pwOrdinal
) *pwOrdinal
= 0;
7673 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7674 return TYPE_E_BADMODULEKIND
;
7676 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7678 dump_TypeInfo(This
);
7680 dump_TLBFuncDescOne(pFDesc
);
7683 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7685 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7687 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7695 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7698 return TYPE_E_ELEMENTNOTFOUND
;
7701 /* internal function to make the inherited interfaces' methods appear
7702 * part of the interface */
7703 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7704 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7706 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7709 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7711 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7713 ITypeInfo
*pSubTypeInfo
;
7715 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7719 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7721 ITypeInfo_Release(pSubTypeInfo
);
7725 *hRefType
-= DISPATCH_HREF_OFFSET
;
7727 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7728 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7733 struct search_res_tlb_params
7739 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7741 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7742 static const WCHAR formatW
[] = {'\\','%','d',0};
7743 WCHAR szPath
[MAX_PATH
+1];
7744 ITypeLib
*pTLib
= NULL
;
7748 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7751 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7754 if (snprintfW(szPath
+ len
, ARRAY_SIZE(szPath
) - len
, formatW
, LOWORD(lpszName
)) < 0)
7757 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7760 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7761 if (IsEqualGUID(params
->guid
, impl
->guid
))
7763 params
->pTLib
= pTLib
;
7764 return FALSE
; /* stop enumeration */
7766 ITypeLib_Release(pTLib
);
7772 /* ITypeInfo::GetRefTypeInfo
7774 * If a type description references other type descriptions, it retrieves
7775 * the referenced type descriptions.
7777 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7780 ITypeInfo
**ppTInfo
)
7782 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7783 HRESULT result
= E_FAIL
;
7786 return E_INVALIDARG
;
7788 if ((INT
)hRefType
< 0) {
7789 ITypeInfoImpl
*pTypeInfoImpl
;
7791 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7792 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7793 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7794 return TYPE_E_ELEMENTNOTFOUND
;
7796 /* when we meet a DUAL typeinfo, we must create the alternate
7799 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7801 *pTypeInfoImpl
= *This
;
7802 pTypeInfoImpl
->ref
= 0;
7803 list_init(&pTypeInfoImpl
->custdata_list
);
7805 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7806 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7808 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7810 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7811 /* the AddRef implicitly adds a reference to the parent typelib, which
7812 * stops the copied data from being destroyed until the new typeinfo's
7813 * refcount goes to zero, but we need to signal to the new instance to
7814 * not free its data structures when it is destroyed */
7815 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7817 ITypeInfo_AddRef(*ppTInfo
);
7820 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7821 (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7823 HREFTYPE href_dispatch
= hRefType
;
7824 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7826 TLBRefType
*ref_type
;
7827 ITypeLib
*pTLib
= NULL
;
7830 if(!(hRefType
& 0x1)){
7831 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7833 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7836 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7837 ITypeInfo_AddRef(*ppTInfo
);
7843 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7845 if(ref_type
->reference
== (hRefType
& (~0x3)))
7848 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7850 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7854 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7856 TRACE("internal reference\n");
7857 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7859 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7860 TRACE("typeinfo in imported typelib that is already loaded\n");
7861 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7862 ITypeLib_AddRef(pTLib
);
7865 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
7866 struct search_res_tlb_params params
;
7869 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7871 /* Search in resource table */
7872 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
7873 params
.pTLib
= NULL
;
7874 EnumResourceNamesW(NULL
, TYPELIBW
, search_res_tlb
, (LONG_PTR
)¶ms
);
7875 pTLib
= params
.pTLib
;
7880 /* Search on disk */
7881 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7882 ref_type
->pImpTLInfo
->wVersionMajor
,
7883 ref_type
->pImpTLInfo
->wVersionMinor
,
7884 This
->pTypeLib
->syskind
,
7885 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7887 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7889 result
= LoadTypeLib(libnam
, &pTLib
);
7890 SysFreeString(libnam
);
7893 if(SUCCEEDED(result
)) {
7894 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7895 ITypeLib_AddRef(pTLib
);
7899 if(SUCCEEDED(result
)) {
7900 if(ref_type
->index
== TLB_REF_USE_GUID
)
7901 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7903 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7906 ITypeLib_Release(pTLib
);
7910 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7911 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7915 /* ITypeInfo::AddressOfMember
7917 * Retrieves the addresses of static functions or variables, such as those
7920 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7921 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7923 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7929 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7931 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7935 module
= LoadLibraryW(dll
);
7938 ERR("couldn't load %s\n", debugstr_w(dll
));
7940 SysFreeString(entry
);
7941 return STG_E_FILENOTFOUND
;
7943 /* FIXME: store library somewhere where we can free it */
7948 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7949 entryA
= heap_alloc(len
);
7950 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7952 *ppv
= GetProcAddress(module
, entryA
);
7954 ERR("function not found %s\n", debugstr_a(entryA
));
7960 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7962 ERR("function not found %d\n", ordinal
);
7966 SysFreeString(entry
);
7969 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7974 /* ITypeInfo::CreateInstance
7976 * Creates a new instance of a type that describes a component object class
7979 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7980 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7982 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7986 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7992 WARN("Not able to aggregate\n");
7993 return CLASS_E_NOAGGREGATION
;
7996 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7997 if(FAILED(hr
)) return hr
;
7999 if(pTA
->typekind
!= TKIND_COCLASS
)
8001 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
8007 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
8010 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
8011 TRACE("GetActiveObject rets %08x\n", hr
);
8014 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
8015 IUnknown_Release(pUnk
);
8020 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
8021 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8025 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8029 /* ITypeInfo::GetMops
8031 * Retrieves marshalling information.
8033 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
8036 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8037 FIXME("(%p %d) stub!\n", This
, memid
);
8042 /* ITypeInfo::GetContainingTypeLib
8044 * Retrieves the containing type library and the index of the type description
8045 * within that type library.
8047 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8048 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8050 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8052 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8054 *pIndex
=This
->index
;
8055 TRACE("returning pIndex=%d\n", *pIndex
);
8059 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8060 ITypeLib_AddRef(*ppTLib
);
8061 TRACE("returning ppTLib=%p\n", *ppTLib
);
8067 /* ITypeInfo::ReleaseTypeAttr
8069 * Releases a TYPEATTR previously returned by Get
8072 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8073 TYPEATTR
* pTypeAttr
)
8075 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8076 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8077 heap_free(pTypeAttr
);
8080 /* ITypeInfo::ReleaseFuncDesc
8082 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8084 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8086 FUNCDESC
*pFuncDesc
)
8088 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8091 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8093 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8094 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8095 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8097 SysFreeString((BSTR
)pFuncDesc
);
8100 /* ITypeInfo::ReleaseVarDesc
8102 * Releases a VARDESC previously returned by GetVarDesc.
8104 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8107 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8108 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8110 TLB_FreeVarDesc(pVarDesc
);
8113 /* ITypeInfo2::GetTypeKind
8115 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8118 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8119 TYPEKIND
*pTypeKind
)
8121 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8122 *pTypeKind
= This
->typeattr
.typekind
;
8123 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8127 /* ITypeInfo2::GetTypeFlags
8129 * Returns the type flags without any allocations. This returns a DWORD type
8130 * flag, which expands the type flags without growing the TYPEATTR (type
8134 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8136 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8137 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8138 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
8142 /* ITypeInfo2::GetFuncIndexOfMemId
8143 * Binds to a specific member based on a known DISPID, where the member name
8144 * is not known (for example, when binding to a default member).
8147 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8148 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8150 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8154 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8155 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8156 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8159 if(fdc
< This
->typeattr
.cFuncs
) {
8163 result
= TYPE_E_ELEMENTNOTFOUND
;
8165 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
8166 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8170 /* TypeInfo2::GetVarIndexOfMemId
8172 * Binds to a specific member based on a known DISPID, where the member name
8173 * is not known (for example, when binding to a default member).
8176 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8177 MEMBERID memid
, UINT
*pVarIndex
)
8179 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8180 TLBVarDesc
*pVarInfo
;
8182 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8184 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
8186 return TYPE_E_ELEMENTNOTFOUND
;
8188 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8193 /* ITypeInfo2::GetCustData
8195 * Gets the custom data
8197 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8202 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8203 TLBCustData
*pCData
;
8205 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8207 if(!guid
|| !pVarVal
)
8208 return E_INVALIDARG
;
8210 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8212 VariantInit( pVarVal
);
8214 VariantCopy( pVarVal
, &pCData
->data
);
8216 VariantClear( pVarVal
);
8220 /* ITypeInfo2::GetFuncCustData
8222 * Gets the custom data
8224 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8230 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8231 TLBCustData
*pCData
;
8232 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8234 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8236 if(index
>= This
->typeattr
.cFuncs
)
8237 return TYPE_E_ELEMENTNOTFOUND
;
8239 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8241 return TYPE_E_ELEMENTNOTFOUND
;
8243 VariantInit(pVarVal
);
8244 VariantCopy(pVarVal
, &pCData
->data
);
8249 /* ITypeInfo2::GetParamCustData
8251 * Gets the custom data
8253 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8260 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8261 TLBCustData
*pCData
;
8262 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8264 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8265 debugstr_guid(guid
), pVarVal
);
8267 if(indexFunc
>= This
->typeattr
.cFuncs
)
8268 return TYPE_E_ELEMENTNOTFOUND
;
8270 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8271 return TYPE_E_ELEMENTNOTFOUND
;
8273 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8275 return TYPE_E_ELEMENTNOTFOUND
;
8277 VariantInit(pVarVal
);
8278 VariantCopy(pVarVal
, &pCData
->data
);
8283 /* ITypeInfo2::GetVarCustData
8285 * Gets the custom data
8287 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8293 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8294 TLBCustData
*pCData
;
8295 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8297 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8299 if(index
>= This
->typeattr
.cVars
)
8300 return TYPE_E_ELEMENTNOTFOUND
;
8302 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8304 return TYPE_E_ELEMENTNOTFOUND
;
8306 VariantInit(pVarVal
);
8307 VariantCopy(pVarVal
, &pCData
->data
);
8312 /* ITypeInfo2::GetImplCustData
8314 * Gets the custom data
8316 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8322 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8323 TLBCustData
*pCData
;
8324 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8326 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8328 if(index
>= This
->typeattr
.cImplTypes
)
8329 return TYPE_E_ELEMENTNOTFOUND
;
8331 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8333 return TYPE_E_ELEMENTNOTFOUND
;
8335 VariantInit(pVarVal
);
8336 VariantCopy(pVarVal
, &pCData
->data
);
8341 /* ITypeInfo2::GetDocumentation2
8343 * Retrieves the documentation string, the complete Help file name and path,
8344 * the localization context to use, and the context ID for the library Help
8345 * topic in the Help file.
8348 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8352 BSTR
*pbstrHelpString
,
8353 DWORD
*pdwHelpStringContext
,
8354 BSTR
*pbstrHelpStringDll
)
8356 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8357 const TLBFuncDesc
*pFDesc
;
8358 const TLBVarDesc
*pVDesc
;
8359 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8360 "HelpStringContext(%p) HelpStringDll(%p)\n",
8361 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8362 pbstrHelpStringDll
);
8363 /* the help string should be obtained from the helpstringdll,
8364 * using the _DLLGetDocumentation function, based on the supplied
8365 * lcid. Nice to do sometime...
8367 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8369 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8370 if(pdwHelpStringContext
)
8371 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8372 if(pbstrHelpStringDll
)
8373 *pbstrHelpStringDll
=
8374 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8376 }else {/* for a member */
8377 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
8380 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8381 if(pdwHelpStringContext
)
8382 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8383 if(pbstrHelpStringDll
)
8384 *pbstrHelpStringDll
=
8385 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8388 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
8391 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8392 if(pdwHelpStringContext
)
8393 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8394 if(pbstrHelpStringDll
)
8395 *pbstrHelpStringDll
=
8396 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8400 return TYPE_E_ELEMENTNOTFOUND
;
8403 /* ITypeInfo2::GetAllCustData
8405 * Gets all custom data items for the Type info.
8408 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8410 CUSTDATA
*pCustData
)
8412 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8414 TRACE("%p %p\n", This
, pCustData
);
8416 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8419 /* ITypeInfo2::GetAllFuncCustData
8421 * Gets all custom data items for the specified Function
8424 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8427 CUSTDATA
*pCustData
)
8429 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8430 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8432 TRACE("%p %u %p\n", This
, index
, pCustData
);
8434 if(index
>= This
->typeattr
.cFuncs
)
8435 return TYPE_E_ELEMENTNOTFOUND
;
8437 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8440 /* ITypeInfo2::GetAllParamCustData
8442 * Gets all custom data items for the Functions
8445 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8446 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8448 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8449 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8451 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8453 if(indexFunc
>= This
->typeattr
.cFuncs
)
8454 return TYPE_E_ELEMENTNOTFOUND
;
8456 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8457 return TYPE_E_ELEMENTNOTFOUND
;
8459 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8462 /* ITypeInfo2::GetAllVarCustData
8464 * Gets all custom data items for the specified Variable
8467 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8468 UINT index
, CUSTDATA
*pCustData
)
8470 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8471 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8473 TRACE("%p %u %p\n", This
, index
, pCustData
);
8475 if(index
>= This
->typeattr
.cVars
)
8476 return TYPE_E_ELEMENTNOTFOUND
;
8478 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8481 /* ITypeInfo2::GetAllImplCustData
8483 * Gets all custom data items for the specified implementation type
8486 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8489 CUSTDATA
*pCustData
)
8491 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8492 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8494 TRACE("%p %u %p\n", This
, index
, pCustData
);
8496 if(index
>= This
->typeattr
.cImplTypes
)
8497 return TYPE_E_ELEMENTNOTFOUND
;
8499 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8502 static const ITypeInfo2Vtbl tinfvt
=
8505 ITypeInfo_fnQueryInterface
,
8507 ITypeInfo_fnRelease
,
8509 ITypeInfo_fnGetTypeAttr
,
8510 ITypeInfo_fnGetTypeComp
,
8511 ITypeInfo_fnGetFuncDesc
,
8512 ITypeInfo_fnGetVarDesc
,
8513 ITypeInfo_fnGetNames
,
8514 ITypeInfo_fnGetRefTypeOfImplType
,
8515 ITypeInfo_fnGetImplTypeFlags
,
8516 ITypeInfo_fnGetIDsOfNames
,
8518 ITypeInfo_fnGetDocumentation
,
8519 ITypeInfo_fnGetDllEntry
,
8520 ITypeInfo_fnGetRefTypeInfo
,
8521 ITypeInfo_fnAddressOfMember
,
8522 ITypeInfo_fnCreateInstance
,
8523 ITypeInfo_fnGetMops
,
8524 ITypeInfo_fnGetContainingTypeLib
,
8525 ITypeInfo_fnReleaseTypeAttr
,
8526 ITypeInfo_fnReleaseFuncDesc
,
8527 ITypeInfo_fnReleaseVarDesc
,
8529 ITypeInfo2_fnGetTypeKind
,
8530 ITypeInfo2_fnGetTypeFlags
,
8531 ITypeInfo2_fnGetFuncIndexOfMemId
,
8532 ITypeInfo2_fnGetVarIndexOfMemId
,
8533 ITypeInfo2_fnGetCustData
,
8534 ITypeInfo2_fnGetFuncCustData
,
8535 ITypeInfo2_fnGetParamCustData
,
8536 ITypeInfo2_fnGetVarCustData
,
8537 ITypeInfo2_fnGetImplTypeCustData
,
8538 ITypeInfo2_fnGetDocumentation2
,
8539 ITypeInfo2_fnGetAllCustData
,
8540 ITypeInfo2_fnGetAllFuncCustData
,
8541 ITypeInfo2_fnGetAllParamCustData
,
8542 ITypeInfo2_fnGetAllVarCustData
,
8543 ITypeInfo2_fnGetAllImplTypeCustData
,
8546 /******************************************************************************
8547 * CreateDispTypeInfo [OLEAUT32.31]
8549 * Build type information for an object so it can be called through an
8550 * IDispatch interface.
8553 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8554 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8557 * This call allows an objects methods to be accessed through IDispatch, by
8558 * building an ITypeInfo object that IDispatch can use to call through.
8560 HRESULT WINAPI
CreateDispTypeInfo(
8561 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8562 LCID lcid
, /* [I] Locale Id */
8563 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8565 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8566 ITypeLibImpl
*pTypeLibImpl
;
8567 unsigned int param
, func
;
8568 TLBFuncDesc
*pFuncDesc
;
8572 pTypeLibImpl
= TypeLibImpl_Constructor();
8573 if (!pTypeLibImpl
) return E_FAIL
;
8575 pTypeLibImpl
->TypeInfoCount
= 2;
8576 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8578 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8579 pTIIface
->pTypeLib
= pTypeLibImpl
;
8580 pTIIface
->index
= 0;
8581 pTIIface
->Name
= NULL
;
8582 pTIIface
->dwHelpContext
= -1;
8583 pTIIface
->guid
= NULL
;
8584 pTIIface
->typeattr
.lcid
= lcid
;
8585 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8586 pTIIface
->typeattr
.wMajorVerNum
= 0;
8587 pTIIface
->typeattr
.wMinorVerNum
= 0;
8588 pTIIface
->typeattr
.cbAlignment
= 2;
8589 pTIIface
->typeattr
.cbSizeInstance
= -1;
8590 pTIIface
->typeattr
.cbSizeVft
= -1;
8591 pTIIface
->typeattr
.cFuncs
= 0;
8592 pTIIface
->typeattr
.cImplTypes
= 0;
8593 pTIIface
->typeattr
.cVars
= 0;
8594 pTIIface
->typeattr
.wTypeFlags
= 0;
8595 pTIIface
->hreftype
= 0;
8597 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8598 pFuncDesc
= pTIIface
->funcdescs
;
8599 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8600 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8601 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8602 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8603 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8604 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8605 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8606 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8607 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8608 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8609 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8610 pFuncDesc
->funcdesc
.cScodes
= 0;
8611 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8612 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8613 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8614 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8615 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8616 md
->cArgs
* sizeof(ELEMDESC
));
8617 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8618 for(param
= 0; param
< md
->cArgs
; param
++) {
8619 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8620 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8622 pFuncDesc
->helpcontext
= 0;
8623 pFuncDesc
->HelpStringContext
= 0;
8624 pFuncDesc
->HelpString
= NULL
;
8625 pFuncDesc
->Entry
= NULL
;
8626 list_init(&pFuncDesc
->custdata_list
);
8627 pTIIface
->typeattr
.cFuncs
++;
8631 dump_TypeInfo(pTIIface
);
8633 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8634 pTIClass
->pTypeLib
= pTypeLibImpl
;
8635 pTIClass
->index
= 1;
8636 pTIClass
->Name
= NULL
;
8637 pTIClass
->dwHelpContext
= -1;
8638 pTIClass
->guid
= NULL
;
8639 pTIClass
->typeattr
.lcid
= lcid
;
8640 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8641 pTIClass
->typeattr
.wMajorVerNum
= 0;
8642 pTIClass
->typeattr
.wMinorVerNum
= 0;
8643 pTIClass
->typeattr
.cbAlignment
= 2;
8644 pTIClass
->typeattr
.cbSizeInstance
= -1;
8645 pTIClass
->typeattr
.cbSizeVft
= -1;
8646 pTIClass
->typeattr
.cFuncs
= 0;
8647 pTIClass
->typeattr
.cImplTypes
= 1;
8648 pTIClass
->typeattr
.cVars
= 0;
8649 pTIClass
->typeattr
.wTypeFlags
= 0;
8650 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8652 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8654 ref
= heap_alloc_zero(sizeof(*ref
));
8655 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8656 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8658 dump_TypeInfo(pTIClass
);
8660 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8662 ITypeInfo_AddRef(*pptinfo
);
8663 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8669 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8671 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8673 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8676 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8678 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8680 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8683 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8685 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8687 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8690 static HRESULT WINAPI
ITypeComp_fnBind(
8695 ITypeInfo
** ppTInfo
,
8696 DESCKIND
* pDescKind
,
8699 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8700 const TLBFuncDesc
*pFDesc
;
8701 const TLBVarDesc
*pVDesc
;
8702 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8705 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8707 *pDescKind
= DESCKIND_NONE
;
8708 pBindPtr
->lpfuncdesc
= NULL
;
8711 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8712 pFDesc
= &This
->funcdescs
[fdc
];
8713 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8714 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8717 /* name found, but wrong flags */
8718 hr
= TYPE_E_TYPEMISMATCH
;
8722 if (fdc
< This
->typeattr
.cFuncs
)
8724 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8726 &pBindPtr
->lpfuncdesc
,
8727 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8730 *pDescKind
= DESCKIND_FUNCDESC
;
8731 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8732 ITypeInfo_AddRef(*ppTInfo
);
8735 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, szName
);
8737 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8740 *pDescKind
= DESCKIND_VARDESC
;
8741 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8742 ITypeInfo_AddRef(*ppTInfo
);
8747 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8748 /* recursive search */
8752 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8755 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8756 ITypeInfo_Release(pTInfo
);
8760 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8761 ITypeComp_Release(pTComp
);
8762 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8763 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8765 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8766 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8767 SysFreeString((BSTR
)tmp
);
8771 WARN("Could not search inherited interface!\n");
8773 if (hr
== DISP_E_MEMBERNOTFOUND
)
8775 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8779 static HRESULT WINAPI
ITypeComp_fnBindType(
8783 ITypeInfo
** ppTInfo
,
8784 ITypeComp
** ppTComp
)
8786 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8788 /* strange behaviour (does nothing) but like the
8791 if (!ppTInfo
|| !ppTComp
)
8800 static const ITypeCompVtbl tcompvt
=
8803 ITypeComp_fnQueryInterface
,
8805 ITypeComp_fnRelease
,
8808 ITypeComp_fnBindType
8811 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8812 ICreateTypeLib2
** ppctlib
)
8817 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8819 if (!szFile
) return E_INVALIDARG
;
8821 This
= TypeLibImpl_Constructor();
8823 return E_OUTOFMEMORY
;
8825 This
->lcid
= GetSystemDefaultLCID();
8826 This
->syskind
= syskind
;
8827 This
->ptr_size
= get_ptr_size(syskind
);
8829 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8831 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8832 return E_OUTOFMEMORY
;
8834 lstrcpyW(This
->path
, szFile
);
8836 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8837 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8841 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8842 REFIID riid
, void **object
)
8844 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8846 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8849 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8851 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8853 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8856 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8858 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8860 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8863 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8864 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8866 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8867 ITypeInfoImpl
*info
;
8870 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8872 if (!ctinfo
|| !name
)
8873 return E_INVALIDARG
;
8875 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8877 return TYPE_E_NAMECONFLICT
;
8879 if (This
->typeinfos
)
8880 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8881 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8883 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8885 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8887 info
->pTypeLib
= This
;
8888 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8889 info
->index
= This
->TypeInfoCount
;
8890 info
->typeattr
.typekind
= kind
;
8891 info
->typeattr
.cbAlignment
= 4;
8893 switch (info
->typeattr
.typekind
) {
8895 case TKIND_INTERFACE
:
8896 case TKIND_DISPATCH
:
8898 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
8902 info
->typeattr
.cbSizeInstance
= 0;
8905 info
->typeattr
.cbSizeInstance
= 2;
8908 info
->typeattr
.cbSizeInstance
= -0x75;
8911 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
8912 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
8916 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8917 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8919 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8923 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8925 ++This
->TypeInfoCount
;
8930 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8933 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8935 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8938 return E_INVALIDARG
;
8940 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8945 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8946 WORD majorVerNum
, WORD minorVerNum
)
8948 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8950 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8952 This
->ver_major
= majorVerNum
;
8953 This
->ver_minor
= minorVerNum
;
8958 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8961 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8963 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8965 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8970 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8973 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8975 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8978 return E_INVALIDARG
;
8980 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8985 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8986 LPOLESTR helpFileName
)
8988 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8990 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8993 return E_INVALIDARG
;
8995 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
9000 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
9003 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9005 TRACE("%p %d\n", This
, helpContext
);
9007 This
->dwHelpContext
= helpContext
;
9012 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
9015 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9017 TRACE("%p %x\n", This
, lcid
);
9019 This
->set_lcid
= lcid
;
9024 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9027 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9029 TRACE("%p %x\n", This
, libFlags
);
9031 This
->libflags
= libFlags
;
9036 typedef struct tagWMSFT_SegContents
{
9039 } WMSFT_SegContents
;
9041 typedef struct tagWMSFT_TLBFile
{
9043 WMSFT_SegContents typeinfo_seg
;
9044 WMSFT_SegContents impfile_seg
;
9045 WMSFT_SegContents impinfo_seg
;
9046 WMSFT_SegContents ref_seg
;
9047 WMSFT_SegContents guidhash_seg
;
9048 WMSFT_SegContents guid_seg
;
9049 WMSFT_SegContents namehash_seg
;
9050 WMSFT_SegContents name_seg
;
9051 WMSFT_SegContents string_seg
;
9052 WMSFT_SegContents typdesc_seg
;
9053 WMSFT_SegContents arraydesc_seg
;
9054 WMSFT_SegContents custdata_seg
;
9055 WMSFT_SegContents cdguids_seg
;
9057 WMSFT_SegContents aux_seg
;
9060 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9061 WMSFT_TLBFile
*file
)
9067 file
->string_seg
.len
= 0;
9068 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9071 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9073 return E_UNEXPECTED
;
9075 size
+= sizeof(INT16
);
9077 size
= (size
+ 4) & ~0x3;
9081 file
->string_seg
.len
+= size
;
9083 /* temporarily use str->offset to store the length of the aligned,
9084 * converted string */
9088 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
9091 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9094 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
9095 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9097 heap_free(file
->string_seg
.data
);
9098 return E_UNEXPECTED
;
9101 *((INT16
*)data
) = size
;
9103 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9107 str
->offset
= last_offs
;
9114 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9115 WMSFT_TLBFile
*file
)
9120 MSFT_NameIntro
*last_intro
= NULL
;
9122 file
->header
.nametablecount
= 0;
9123 file
->header
.nametablechars
= 0;
9125 file
->name_seg
.len
= 0;
9126 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9129 size
= strlenW(str
->str
);
9130 file
->header
.nametablechars
+= size
;
9131 file
->header
.nametablecount
++;
9133 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9135 return E_UNEXPECTED
;
9137 size
+= sizeof(MSFT_NameIntro
);
9139 size
= (size
+ 4) & ~0x3;
9143 file
->name_seg
.len
+= size
;
9145 /* temporarily use str->offset to store the length of the aligned,
9146 * converted string */
9150 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9151 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
9154 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9156 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9158 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
9159 data
+ sizeof(MSFT_NameIntro
),
9160 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9162 heap_free(file
->name_seg
.data
);
9163 return E_UNEXPECTED
;
9165 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9167 intro
->hreftype
= -1; /* TODO? */
9168 intro
->namelen
= size
& 0xFF;
9169 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9170 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9171 intro
->namelen
|= hash
<< 16;
9172 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9173 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9175 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9176 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9178 /* update str->offset to actual value to use in other
9179 * compilation functions that require positions within
9180 * the string table */
9184 str
->offset
= last_offs
;
9189 last_intro
->hreftype
= 0; /* last one is 0? */
9194 static inline int hash_guid(GUID
*guid
)
9198 for (i
= 0; i
< 8; i
++)
9199 hash
^= ((const short *)guid
)[i
];
9204 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9207 MSFT_GuidEntry
*entry
;
9209 int hash_key
, *guidhashtab
;
9211 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9212 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9214 entry
= file
->guid_seg
.data
;
9216 guidhashtab
= file
->guidhash_seg
.data
;
9217 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9218 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9219 entry
->hreftype
= guid
->hreftype
;
9221 hash_key
= hash_guid(&guid
->guid
);
9222 entry
->next_hash
= guidhashtab
[hash_key
];
9223 guidhashtab
[hash_key
] = offs
;
9225 guid
->offset
= offs
;
9226 offs
+= sizeof(MSFT_GuidEntry
);
9233 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9236 VARTYPE arg_type
= V_VT(value
);
9239 DWORD ret
= file
->custdata_seg
.len
;
9241 if(arg_type
== VT_INT
)
9243 if(arg_type
== VT_UINT
)
9247 if(V_VT(value
) != arg_type
) {
9248 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9250 ERR("VariantChangeType failed: %08x\n", hres
);
9255 /* Check if default value can be stored in-place */
9260 if(V_UI4(&v
) > 0x3ffffff)
9273 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9276 /* have to allocate space in custdata_seg */
9285 /* Construct the data to be allocated */
9288 if(file
->custdata_seg
.data
){
9289 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9290 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9291 file
->custdata_seg
.len
+= sizeof(int) * 2;
9293 file
->custdata_seg
.len
= sizeof(int) * 2;
9294 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9297 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9298 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9300 /* TODO: Check if the encoded data is already present in custdata_seg */
9306 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9309 if(file
->custdata_seg
.data
){
9310 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9311 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9312 file
->custdata_seg
.len
+= len
;
9314 file
->custdata_seg
.len
= len
;
9315 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9318 *((unsigned short *)data
) = V_VT(value
);
9319 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9320 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9321 if(V_BSTR(&v
)[i
] <= 0x7f)
9322 data
[i
+6] = V_BSTR(&v
)[i
];
9326 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9327 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9330 /* TODO: Check if the encoded data is already present in custdata_seg */
9335 FIXME("Argument type not yet handled\n");
9340 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9342 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9344 DWORD offs
= file
->arraydesc_seg
.len
;
9348 /* TODO: we should check for duplicates, but that's harder because each
9349 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9350 * at the library-level) */
9352 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9353 if(!file
->arraydesc_seg
.data
)
9354 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9356 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9357 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9359 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9360 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9361 for(i
= 0; i
< desc
->cDims
; ++i
){
9362 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9363 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9369 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9375 VARTYPE vt
, subtype
;
9386 vt
= desc
->vt
& VT_TYPEMASK
;
9388 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9390 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9391 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9393 *out_size
+= 2 * sizeof(DWORD
);
9394 }else if(vt
== VT_CARRAY
){
9395 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9396 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9398 }else if(vt
== VT_USERDEFINED
){
9399 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9400 encoded
[1] = desc
->u
.hreftype
;
9401 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9403 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9421 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9424 data
= file
->typdesc_seg
.data
;
9425 while(offs
< file
->typdesc_seg
.len
){
9426 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9428 offs
+= sizeof(encoded
);
9431 file
->typdesc_seg
.len
+= sizeof(encoded
);
9432 if(!file
->typdesc_seg
.data
)
9433 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9435 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9437 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9442 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9444 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9445 DWORD ret
= cdguids_seg
->len
, offs
;
9446 MSFT_CDGuid
*cdguid
;
9449 if(list_empty(custdata_list
))
9452 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9453 if(!cdguids_seg
->data
){
9454 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9456 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9457 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9460 offs
= ret
+ sizeof(MSFT_CDGuid
);
9461 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9462 cdguid
->GuidOffset
= cd
->guid
->offset
;
9463 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9464 cdguid
->next
= offs
;
9465 offs
+= sizeof(MSFT_CDGuid
);
9475 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9476 WMSFT_TLBFile
*file
)
9478 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9479 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9480 MSFT_VarRecord
*varrecord
;
9481 MSFT_FuncRecord
*funcrecord
;
9483 DWORD
*name
, *offsets
, offs
;
9485 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9486 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9488 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9490 /* optional fields */
9491 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9492 if(!list_empty(&desc
->custdata_list
))
9493 recorded_size
+= 7 * sizeof(INT
);
9494 else if(desc
->HelpStringContext
!= 0)
9495 recorded_size
+= 6 * sizeof(INT
);
9497 else if(desc
->Entry
)
9498 recorded_size
+= 3 * sizeof(INT
);
9499 else if(desc
->HelpString
)
9500 recorded_size
+= 2 * sizeof(INT
);
9501 else if(desc
->helpcontext
)
9502 recorded_size
+= sizeof(INT
);
9504 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9506 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9507 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9508 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9513 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9516 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9517 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9519 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9521 /* optional fields */
9522 if(desc
->HelpStringContext
!= 0)
9523 recorded_size
+= 5 * sizeof(INT
);
9524 else if(!list_empty(&desc
->custdata_list
))
9525 recorded_size
+= 4 * sizeof(INT
);
9527 else if(desc
->HelpString
)
9528 recorded_size
+= 2 * sizeof(INT
);
9529 else if(desc
->HelpContext
!= 0)
9530 recorded_size
+= sizeof(INT
);
9532 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9535 if(!recorded_size
&& !extra_size
)
9538 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9540 aux_seg
->len
+= recorded_size
+ extra_size
;
9542 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9545 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9547 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9549 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9551 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9554 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9555 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9556 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9557 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9559 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9560 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9561 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9562 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9565 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9570 * ^has_param_defaults
9571 * ^oEntry_is_intresource
9573 funcrecord
->FKCCIC
=
9574 desc
->funcdesc
.funckind
|
9575 (desc
->funcdesc
.invkind
<< 3) |
9576 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9577 (desc
->funcdesc
.callconv
<< 8);
9579 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9580 funcrecord
->FKCCIC
|= 0x2000;
9582 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9583 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9584 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9585 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9588 if(paramdefault_size
> 0)
9589 funcrecord
->FKCCIC
|= 0x1000;
9591 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9592 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9594 /* optional fields */
9596 if(!list_empty(&desc
->custdata_list
)){
9597 size
+= 7 * sizeof(INT
);
9598 funcrecord
->HelpContext
= desc
->helpcontext
;
9599 if(desc
->HelpString
)
9600 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9602 funcrecord
->oHelpString
= -1;
9604 funcrecord
->oEntry
= -1;
9605 else if(IS_INTRESOURCE(desc
->Entry
))
9606 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9608 funcrecord
->oEntry
= desc
->Entry
->offset
;
9609 funcrecord
->res9
= -1;
9610 funcrecord
->resA
= -1;
9611 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9612 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9613 }else if(desc
->HelpStringContext
!= 0){
9614 size
+= 6 * sizeof(INT
);
9615 funcrecord
->HelpContext
= desc
->helpcontext
;
9616 if(desc
->HelpString
)
9617 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9619 funcrecord
->oHelpString
= -1;
9621 funcrecord
->oEntry
= -1;
9622 else if(IS_INTRESOURCE(desc
->Entry
))
9623 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9625 funcrecord
->oEntry
= desc
->Entry
->offset
;
9626 funcrecord
->res9
= -1;
9627 funcrecord
->resA
= -1;
9628 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9629 }else if(desc
->Entry
){
9630 size
+= 3 * sizeof(INT
);
9631 funcrecord
->HelpContext
= desc
->helpcontext
;
9632 if(desc
->HelpString
)
9633 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9635 funcrecord
->oHelpString
= -1;
9637 funcrecord
->oEntry
= -1;
9638 else if(IS_INTRESOURCE(desc
->Entry
))
9639 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9641 funcrecord
->oEntry
= desc
->Entry
->offset
;
9642 }else if(desc
->HelpString
){
9643 size
+= 2 * sizeof(INT
);
9644 funcrecord
->HelpContext
= desc
->helpcontext
;
9645 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9646 }else if(desc
->helpcontext
){
9647 size
+= sizeof(INT
);
9648 funcrecord
->HelpContext
= desc
->helpcontext
;
9651 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9652 size
+= paramdefault_size
;
9654 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9655 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9657 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9658 if(desc
->pParamDesc
[j
].Name
)
9659 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9662 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9664 if(paramdefault_size
){
9665 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9666 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9667 else if(paramdefault_size
)
9672 size
+= sizeof(MSFT_ParameterInfo
);
9675 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9681 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9684 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9685 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9686 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9687 DWORD size
= 5 * sizeof(INT
);
9689 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9690 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9691 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9692 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9694 if(desc
->vardesc
.varkind
== VAR_CONST
){
9695 varrecord
->vardescsize
+= sizeof(VARIANT
);
9696 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9698 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9701 if(desc
->HelpStringContext
!= 0){
9702 size
+= 5 * sizeof(INT
);
9703 varrecord
->HelpContext
= desc
->HelpContext
;
9704 if(desc
->HelpString
)
9705 varrecord
->HelpString
= desc
->HelpString
->offset
;
9707 varrecord
->HelpString
= -1;
9708 varrecord
->res9
= -1;
9709 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9710 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9711 }else if(!list_empty(&desc
->custdata_list
)){
9712 size
+= 4 * sizeof(INT
);
9713 varrecord
->HelpContext
= desc
->HelpContext
;
9714 if(desc
->HelpString
)
9715 varrecord
->HelpString
= desc
->HelpString
->offset
;
9717 varrecord
->HelpString
= -1;
9718 varrecord
->res9
= -1;
9719 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9720 }else if(desc
->HelpString
){
9721 size
+= 2 * sizeof(INT
);
9722 varrecord
->HelpContext
= desc
->HelpContext
;
9723 if(desc
->HelpString
)
9724 varrecord
->HelpString
= desc
->HelpString
->offset
;
9726 varrecord
->HelpString
= -1;
9727 }else if(desc
->HelpContext
!= 0){
9728 size
+= sizeof(INT
);
9729 varrecord
->HelpContext
= desc
->HelpContext
;
9732 varrecord
->Info
= size
| (i
<< 16);
9738 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9741 memid
= (MEMBERID
*)varrecord
;
9742 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9743 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9744 *memid
= desc
->funcdesc
.memid
;
9747 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9748 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9749 *memid
= desc
->vardesc
.memid
;
9753 name
= (UINT
*)memid
;
9754 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9755 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9757 *name
= desc
->Name
->offset
;
9762 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9763 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9765 *name
= desc
->Name
->offset
;
9774 typedef struct tagWMSFT_RefChunk
{
9781 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9783 DWORD offs
= file
->ref_seg
.len
, i
;
9784 WMSFT_RefChunk
*chunk
;
9786 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9787 if(!file
->ref_seg
.data
)
9788 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9790 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9792 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9794 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9795 chunk
->href
= info
->impltypes
[i
].hRef
;
9796 chunk
->res04
= info
->impltypes
[i
].implflags
;
9798 if(i
< info
->typeattr
.cImplTypes
- 1)
9799 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9808 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9812 size
= sizeof(MSFT_TypeInfoBase
);
9815 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9816 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9817 base
->typekind
= TKIND_DISPATCH
;
9819 base
->typekind
= info
->typeattr
.typekind
;
9820 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9821 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
9822 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9827 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
9833 base
->posguid
= info
->guid
->offset
;
9836 base
->flags
= info
->typeattr
.wTypeFlags
;
9838 base
->NameOffset
= info
->Name
->offset
;
9840 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9841 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9843 base
->NameOffset
= -1;
9845 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
9847 base
->docstringoffs
= info
->DocString
->offset
;
9849 base
->docstringoffs
= -1;
9850 base
->helpstringcontext
= info
->dwHelpStringContext
;
9851 base
->helpcontext
= info
->dwHelpContext
;
9852 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9853 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
9854 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
9855 base
->size
= info
->typeattr
.cbSizeInstance
;
9856 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
9857 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9858 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
9859 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9860 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
9862 base
->datatype1
= info
->DllName
->offset
;
9864 base
->datatype1
= -1;
9866 if(info
->typeattr
.cImplTypes
> 0)
9867 base
->datatype1
= info
->impltypes
[0].hRef
;
9869 base
->datatype1
= -1;
9871 base
->datatype2
= index
; /* FIXME: i think there's more here */
9879 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9883 file
->typeinfo_seg
.len
= 0;
9884 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9885 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9886 *junk
= file
->typeinfo_seg
.len
;
9888 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9891 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9892 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9894 file
->aux_seg
.len
= 0;
9895 file
->aux_seg
.data
= NULL
;
9897 file
->typeinfo_seg
.len
= 0;
9898 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9899 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9900 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9901 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9905 typedef struct tagWMSFT_ImpFile
{
9911 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9914 WMSFT_ImpFile
*impfile
;
9916 DWORD last_offs
= 0;
9918 file
->impfile_seg
.len
= 0;
9919 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9923 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9927 path
= implib
->name
;
9928 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9930 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9933 size
+= sizeof(INT16
);
9935 size
= (size
+ 4) & ~0x3;
9939 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9942 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9944 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9945 int strlen
= 0, size
;
9947 impfile
= (WMSFT_ImpFile
*)data
;
9948 impfile
->guid_offs
= implib
->guid
->offset
;
9949 impfile
->lcid
= implib
->lcid
;
9950 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9952 data
+= sizeof(WMSFT_ImpFile
);
9955 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9959 path
= implib
->name
;
9960 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9961 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9963 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9966 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9968 size
= strlen
+ sizeof(INT16
);
9970 size
= (size
+ 4) & ~0x3;
9973 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9976 implib
->offset
= last_offs
;
9977 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9981 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9984 TLBRefType
*ref_type
;
9987 WMSFT_compile_impfile(This
, file
);
9989 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9990 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9992 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9993 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9994 if(ref_type
->index
== TLB_REF_USE_GUID
){
9995 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9996 info
->oGuid
= ref_type
->guid
->offset
;
9998 info
->oGuid
= ref_type
->index
;
9999 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
10005 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10007 file
->guidhash_seg
.len
= 0x80;
10008 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
10009 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
10012 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10014 file
->namehash_seg
.len
= 0x200;
10015 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
10016 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
10019 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
10021 if(contents
&& contents
->len
){
10022 segdir
->offset
= *running_offset
;
10023 segdir
->length
= contents
->len
;
10024 *running_offset
+= segdir
->length
;
10026 segdir
->offset
= -1;
10027 segdir
->length
= 0;
10030 /* TODO: do these ever change? */
10031 segdir
->res08
= -1;
10032 segdir
->res0c
= 0xf;
10035 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10039 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10042 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10046 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10048 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10049 base
->memoffset
+= file_len
;
10056 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10058 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
10059 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
10060 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
10061 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
10062 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
10063 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
10064 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
10065 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
10066 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
10067 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
10068 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
10069 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
10070 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
10071 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
10074 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10076 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10077 WMSFT_TLBFile file
;
10078 DWORD written
, junk_size
, junk_offs
, running_offset
;
10085 TRACE("%p\n", This
);
10087 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10088 if(This
->typeinfos
[i
]->needs_layout
)
10089 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10091 memset(&file
, 0, sizeof(file
));
10093 file
.header
.magic1
= 0x5446534D;
10094 file
.header
.magic2
= 0x00010002;
10095 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10096 file
.header
.lcid2
= This
->set_lcid
;
10097 file
.header
.varflags
= 0x40 | This
->syskind
;
10098 if (This
->HelpFile
)
10099 file
.header
.varflags
|= 0x10;
10100 if (This
->HelpStringDll
)
10101 file
.header
.varflags
|= HELPDLLFLAG
;
10102 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10103 file
.header
.flags
= This
->libflags
;
10104 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10105 file
.header
.helpcontext
= This
->dwHelpContext
;
10106 file
.header
.res44
= 0x20;
10107 file
.header
.res48
= 0x80;
10108 file
.header
.dispatchpos
= This
->dispatch_href
;
10110 WMSFT_compile_namehash(This
, &file
);
10111 /* do name and string compilation to get offsets for other compilations */
10112 hres
= WMSFT_compile_names(This
, &file
);
10114 WMSFT_free_file(&file
);
10118 hres
= WMSFT_compile_strings(This
, &file
);
10120 WMSFT_free_file(&file
);
10124 WMSFT_compile_guidhash(This
, &file
);
10125 hres
= WMSFT_compile_guids(This
, &file
);
10127 WMSFT_free_file(&file
);
10132 file
.header
.helpfile
= This
->HelpFile
->offset
;
10134 file
.header
.helpfile
= -1;
10136 if(This
->DocString
)
10137 file
.header
.helpstring
= This
->DocString
->offset
;
10139 file
.header
.helpstring
= -1;
10141 /* do some more segment compilation */
10142 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10143 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10146 file
.header
.NameOffset
= This
->Name
->offset
;
10148 file
.header
.NameOffset
= -1;
10150 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10153 file
.header
.posguid
= This
->guid
->offset
;
10155 file
.header
.posguid
= -1;
10157 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10158 if(file
.header
.varflags
& HELPDLLFLAG
)
10159 junk_size
+= sizeof(DWORD
);
10161 junk
= heap_alloc_zero(junk_size
);
10162 if(file
.header
.varflags
& HELPDLLFLAG
){
10163 *junk
= This
->HelpStringDll
->offset
;
10172 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10173 WMSFT_compile_impinfo(This
, &file
);
10175 running_offset
= 0;
10177 TRACE("header at: 0x%x\n", running_offset
);
10178 running_offset
+= sizeof(file
.header
);
10180 TRACE("junk at: 0x%x\n", running_offset
);
10181 running_offset
+= junk_size
;
10183 TRACE("segdir at: 0x%x\n", running_offset
);
10184 running_offset
+= sizeof(file
.segdir
);
10186 TRACE("typeinfo at: 0x%x\n", running_offset
);
10187 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10189 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10190 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10192 TRACE("guidtab at: 0x%x\n", running_offset
);
10193 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10195 TRACE("reftab at: 0x%x\n", running_offset
);
10196 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10198 TRACE("impinfo at: 0x%x\n", running_offset
);
10199 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10201 TRACE("impfiles at: 0x%x\n", running_offset
);
10202 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10204 TRACE("namehashtab at: 0x%x\n", running_offset
);
10205 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10207 TRACE("nametab at: 0x%x\n", running_offset
);
10208 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10210 TRACE("stringtab at: 0x%x\n", running_offset
);
10211 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10213 TRACE("typdesc at: 0x%x\n", running_offset
);
10214 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10216 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10217 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10219 TRACE("custdata at: 0x%x\n", running_offset
);
10220 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10222 TRACE("cdguids at: 0x%x\n", running_offset
);
10223 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10225 TRACE("res0e at: 0x%x\n", running_offset
);
10226 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10228 TRACE("res0f at: 0x%x\n", running_offset
);
10229 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10231 TRACE("aux_seg at: 0x%x\n", running_offset
);
10233 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10235 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10236 FILE_ATTRIBUTE_NORMAL
, 0);
10237 if (outfile
== INVALID_HANDLE_VALUE
){
10238 WMSFT_free_file(&file
);
10240 return TYPE_E_IOERROR
;
10243 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10245 WMSFT_free_file(&file
);
10246 CloseHandle(outfile
);
10248 return TYPE_E_IOERROR
;
10251 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10254 WMSFT_free_file(&file
);
10255 CloseHandle(outfile
);
10256 return TYPE_E_IOERROR
;
10259 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10261 WMSFT_free_file(&file
);
10262 CloseHandle(outfile
);
10263 return TYPE_E_IOERROR
;
10266 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10267 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10268 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10269 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10270 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10271 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10272 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10273 WMSFT_write_segment(outfile
, &file
.name_seg
);
10274 WMSFT_write_segment(outfile
, &file
.string_seg
);
10275 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10276 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10277 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10278 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10279 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10281 WMSFT_free_file(&file
);
10283 CloseHandle(outfile
);
10288 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10291 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10292 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10296 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10297 REFGUID guid
, VARIANT
*varVal
)
10299 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10302 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10304 if (!guid
|| !varVal
)
10305 return E_INVALIDARG
;
10307 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10309 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10312 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10313 ULONG helpStringContext
)
10315 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10316 FIXME("%p %u - stub\n", This
, helpStringContext
);
10320 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10323 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10324 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10327 return E_INVALIDARG
;
10329 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10334 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10335 ICreateTypeLib2_fnQueryInterface
,
10336 ICreateTypeLib2_fnAddRef
,
10337 ICreateTypeLib2_fnRelease
,
10338 ICreateTypeLib2_fnCreateTypeInfo
,
10339 ICreateTypeLib2_fnSetName
,
10340 ICreateTypeLib2_fnSetVersion
,
10341 ICreateTypeLib2_fnSetGuid
,
10342 ICreateTypeLib2_fnSetDocString
,
10343 ICreateTypeLib2_fnSetHelpFileName
,
10344 ICreateTypeLib2_fnSetHelpContext
,
10345 ICreateTypeLib2_fnSetLcid
,
10346 ICreateTypeLib2_fnSetLibFlags
,
10347 ICreateTypeLib2_fnSaveAllChanges
,
10348 ICreateTypeLib2_fnDeleteTypeInfo
,
10349 ICreateTypeLib2_fnSetCustData
,
10350 ICreateTypeLib2_fnSetHelpStringContext
,
10351 ICreateTypeLib2_fnSetHelpStringDll
10354 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10355 REFIID riid
, void **object
)
10357 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10359 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10362 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10364 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10366 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10369 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10371 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10373 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10376 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10379 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10381 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10383 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10388 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10391 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10395 TRACE("%p %x\n", This
, typeFlags
);
10397 if (typeFlags
& TYPEFLAG_FDUAL
) {
10398 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10400 ITypeInfo
*dispatch
;
10404 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10408 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10409 ITypeLib_Release(stdole
);
10413 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10414 ITypeInfo_Release(dispatch
);
10419 old_flags
= This
->typeattr
.wTypeFlags
;
10420 This
->typeattr
.wTypeFlags
= typeFlags
;
10422 hres
= ICreateTypeInfo2_LayOut(iface
);
10423 if (FAILED(hres
)) {
10424 This
->typeattr
.wTypeFlags
= old_flags
;
10431 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10434 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10436 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10439 return E_INVALIDARG
;
10441 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10446 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10449 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10451 TRACE("%p %d\n", This
, helpContext
);
10453 This
->dwHelpContext
= helpContext
;
10458 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10459 WORD majorVerNum
, WORD minorVerNum
)
10461 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10463 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10465 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10466 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10471 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10472 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10474 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10476 ITypeLib
*container
;
10477 TLBRefType
*ref_type
;
10479 TYPEATTR
*typeattr
;
10483 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10485 if (!typeInfo
|| !refType
)
10486 return E_INVALIDARG
;
10488 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10492 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10493 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10495 ITypeLib_Release(container
);
10497 *refType
= target
->hreftype
;
10502 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10503 if (FAILED(hres
)) {
10504 ITypeLib_Release(container
);
10508 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10509 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10510 implib
->lcid
== libattr
->lcid
&&
10511 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10512 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10516 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10517 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10519 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10520 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10521 implib
->name
= SysAllocString(our_container
->path
);
10523 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10524 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10526 implib
->name
= NULL
;
10527 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10531 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10532 implib
->lcid
= libattr
->lcid
;
10533 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10534 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10536 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10539 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10540 ITypeLib_Release(container
);
10542 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10547 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10548 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10549 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10550 ref_type
->tkind
== typeattr
->typekind
)
10555 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10556 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10558 ref_type
->tkind
= typeattr
->typekind
;
10559 ref_type
->pImpTLInfo
= implib
;
10560 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10562 ref_type
->index
= TLB_REF_USE_GUID
;
10564 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10566 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10569 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10571 *refType
= ref_type
->reference
| 0x1;
10573 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10574 This
->pTypeLib
->dispatch_href
= *refType
;
10579 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10580 UINT index
, FUNCDESC
*funcDesc
)
10582 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10583 TLBFuncDesc tmp_func_desc
, *func_desc
;
10588 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10590 if (!funcDesc
|| funcDesc
->oVft
& 3)
10591 return E_INVALIDARG
;
10593 switch (This
->typeattr
.typekind
) {
10595 if (funcDesc
->funckind
!= FUNC_STATIC
)
10596 return TYPE_E_BADMODULEKIND
;
10598 case TKIND_DISPATCH
:
10599 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10600 return TYPE_E_BADMODULEKIND
;
10603 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10604 return TYPE_E_BADMODULEKIND
;
10607 if (index
> This
->typeattr
.cFuncs
)
10608 return TYPE_E_ELEMENTNOTFOUND
;
10610 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10611 !funcDesc
->cParams
)
10612 return TYPE_E_INCONSISTENTPROPFUNCS
;
10615 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10616 funcDesc
->oVft
% 8 != 0)
10617 return E_INVALIDARG
;
10620 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10621 TLBFuncDesc_Constructor(&tmp_func_desc
);
10623 tmp_func_desc
.funcdesc
= *funcDesc
;
10625 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10626 tmp_func_desc
.funcdesc
.oVft
|= 1;
10628 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10629 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10630 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10632 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10633 tmp_func_desc
.funcdesc
.cScodes
= 0;
10636 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10637 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10638 buf_size
+= sizeof(ELEMDESC
);
10639 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10641 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10642 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10644 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10645 if (FAILED(hres
)) {
10646 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10647 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10651 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10652 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10653 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10654 if (FAILED(hres
)) {
10655 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10656 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10659 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10660 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10661 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10662 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10663 if (FAILED(hres
)) {
10664 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10665 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10671 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10673 if (This
->funcdescs
) {
10674 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10675 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10677 if (index
< This
->typeattr
.cFuncs
) {
10678 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10679 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10680 func_desc
= This
->funcdescs
+ index
;
10682 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10684 /* move custdata lists to the new memory location */
10685 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10687 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10688 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10689 list_init(&fd
->custdata_list
);
10691 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10692 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10697 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10699 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10700 list_init(&func_desc
->custdata_list
);
10702 ++This
->typeattr
.cFuncs
;
10704 This
->needs_layout
= TRUE
;
10709 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10710 UINT index
, HREFTYPE refType
)
10712 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10713 TLBImplType
*impl_type
;
10716 TRACE("%p %u %d\n", This
, index
, refType
);
10718 switch(This
->typeattr
.typekind
){
10719 case TKIND_COCLASS
: {
10721 FIXME("Unhandled index: -1\n");
10725 if(index
!= This
->typeattr
.cImplTypes
)
10726 return TYPE_E_ELEMENTNOTFOUND
;
10730 case TKIND_INTERFACE
:
10731 case TKIND_DISPATCH
:
10732 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10733 return TYPE_E_ELEMENTNOTFOUND
;
10736 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10740 if (This
->impltypes
){
10743 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10744 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10746 if (index
< This
->typeattr
.cImplTypes
) {
10747 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10748 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10749 impl_type
= This
->impltypes
+ index
;
10751 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10753 /* move custdata lists to the new memory location */
10754 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10756 TLBImplType
*it
= &This
->impltypes
[i
];
10757 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10758 list_init(&it
->custdata_list
);
10760 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10761 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10766 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10768 memset(impl_type
, 0, sizeof(TLBImplType
));
10769 TLBImplType_Constructor(impl_type
);
10770 impl_type
->hRef
= refType
;
10772 ++This
->typeattr
.cImplTypes
;
10774 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10775 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10777 hres
= ICreateTypeInfo2_LayOut(iface
);
10784 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10785 UINT index
, INT implTypeFlags
)
10787 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10788 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10790 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10792 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10793 return TYPE_E_BADMODULEKIND
;
10795 if (index
>= This
->typeattr
.cImplTypes
)
10796 return TYPE_E_ELEMENTNOTFOUND
;
10798 impl_type
->implflags
= implTypeFlags
;
10803 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10806 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10808 TRACE("%p %d\n", This
, alignment
);
10810 This
->typeattr
.cbAlignment
= alignment
;
10815 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10818 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10820 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10823 return E_INVALIDARG
;
10825 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10827 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10832 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10833 UINT index
, VARDESC
*varDesc
)
10835 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10836 TLBVarDesc
*var_desc
;
10838 TRACE("%p %u %p\n", This
, index
, varDesc
);
10840 if (This
->vardescs
){
10843 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10844 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
10846 if (index
< This
->typeattr
.cVars
) {
10847 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10848 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
10849 var_desc
= This
->vardescs
+ index
;
10851 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
10853 /* move custdata lists to the new memory location */
10854 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
10856 TLBVarDesc
*var
= &This
->vardescs
[i
];
10857 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10858 list_init(&var
->custdata_list
);
10860 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10861 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10866 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10868 TLBVarDesc_Constructor(var_desc
);
10869 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10870 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10872 ++This
->typeattr
.cVars
;
10874 This
->needs_layout
= TRUE
;
10879 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10880 UINT index
, LPOLESTR
*names
, UINT numNames
)
10882 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10883 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10886 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10889 return E_INVALIDARG
;
10891 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
10892 return TYPE_E_ELEMENTNOTFOUND
;
10894 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10895 if(numNames
> func_desc
->funcdesc
.cParams
)
10896 return TYPE_E_ELEMENTNOTFOUND
;
10898 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10899 return TYPE_E_ELEMENTNOTFOUND
;
10901 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
10902 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10903 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10904 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10905 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10906 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10908 return TYPE_E_AMBIGUOUSNAME
;
10912 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10914 for (i
= 1; i
< numNames
; ++i
) {
10915 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10916 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10922 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10923 UINT index
, LPOLESTR name
)
10925 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10927 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10930 return E_INVALIDARG
;
10932 if(index
>= This
->typeattr
.cVars
)
10933 return TYPE_E_ELEMENTNOTFOUND
;
10935 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10939 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10940 TYPEDESC
*tdescAlias
)
10942 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10945 TRACE("%p %p\n", This
, tdescAlias
);
10948 return E_INVALIDARG
;
10950 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
10951 return TYPE_E_BADMODULEKIND
;
10953 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
10957 heap_free(This
->tdescAlias
);
10958 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10959 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10964 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10965 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10967 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10968 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10972 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10973 UINT index
, LPOLESTR docString
)
10975 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10976 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10978 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10981 return E_INVALIDARG
;
10983 if(index
>= This
->typeattr
.cFuncs
)
10984 return TYPE_E_ELEMENTNOTFOUND
;
10986 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10991 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10992 UINT index
, LPOLESTR docString
)
10994 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10995 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10997 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11000 return E_INVALIDARG
;
11002 if(index
>= This
->typeattr
.cVars
)
11003 return TYPE_E_ELEMENTNOTFOUND
;
11005 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11010 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
11011 UINT index
, DWORD helpContext
)
11013 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11014 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11016 TRACE("%p %u %d\n", This
, index
, helpContext
);
11018 if(index
>= This
->typeattr
.cFuncs
)
11019 return TYPE_E_ELEMENTNOTFOUND
;
11021 func_desc
->helpcontext
= helpContext
;
11026 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
11027 UINT index
, DWORD helpContext
)
11029 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11030 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11032 TRACE("%p %u %d\n", This
, index
, helpContext
);
11034 if(index
>= This
->typeattr
.cVars
)
11035 return TYPE_E_ELEMENTNOTFOUND
;
11037 var_desc
->HelpContext
= helpContext
;
11042 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
11043 UINT index
, BSTR bstrMops
)
11045 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11046 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
11050 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
11053 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11055 TRACE("%p %p\n", This
, idlDesc
);
11058 return E_INVALIDARG
;
11060 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11061 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11066 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11068 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11070 TLBFuncDesc
*func_desc
;
11071 UINT user_vft
= 0, i
, depth
= 0;
11072 HRESULT hres
= S_OK
;
11074 TRACE("%p\n", This
);
11076 This
->needs_layout
= FALSE
;
11078 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
11082 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11087 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11089 if (SUCCEEDED(hres
)) {
11090 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11092 if (SUCCEEDED(hres
)) {
11093 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11094 if (FAILED(hres
)) {
11095 ITypeInfo_Release(inh
);
11096 ITypeInfo_Release(tinfo
);
11099 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11100 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11104 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11105 if(SUCCEEDED(hres
)){
11107 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11108 if(SUCCEEDED(hres
)){
11109 ITypeInfo_Release(inh
);
11113 }while(SUCCEEDED(hres
));
11116 ITypeInfo_Release(inh
);
11117 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11118 This
->typeattr
.cbSizeVft
= 0;
11121 ITypeInfo_Release(tinfo
);
11124 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11125 This
->typeattr
.cbSizeVft
= 0;
11128 ITypeInfo_Release(tinfo
);
11131 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11132 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11134 This
->typeattr
.cbSizeVft
= 0;
11136 func_desc
= This
->funcdescs
;
11138 while (i
< This
->typeattr
.cFuncs
) {
11139 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11140 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11142 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11143 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11145 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11147 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11150 BOOL reset
= FALSE
;
11152 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11154 iter
= This
->funcdescs
;
11155 while (j
< This
->typeattr
.cFuncs
) {
11156 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11158 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11161 ++func_desc
->funcdesc
.memid
;
11162 iter
= This
->funcdescs
;
11175 if (user_vft
> This
->typeattr
.cbSizeVft
)
11176 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11178 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11179 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11180 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11182 BOOL reset
= FALSE
;
11185 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11187 iter
= This
->vardescs
;
11188 while (j
< This
->typeattr
.cVars
) {
11189 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11191 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11194 ++var_desc
->vardesc
.memid
;
11195 iter
= This
->vardescs
;
11205 ITypeInfo_Release(tinfo
);
11209 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11212 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11213 FIXME("%p %u - stub\n", This
, index
);
11217 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11218 MEMBERID memid
, INVOKEKIND invKind
)
11220 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11221 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11225 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11228 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11229 FIXME("%p %u - stub\n", This
, index
);
11233 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11236 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11237 FIXME("%p %x - stub\n", This
, memid
);
11241 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11244 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11245 FIXME("%p %u - stub\n", This
, index
);
11249 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11250 REFGUID guid
, VARIANT
*varVal
)
11254 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11256 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11258 if (!guid
|| !varVal
)
11259 return E_INVALIDARG
;
11261 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11263 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11266 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11267 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11269 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11270 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11274 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11275 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11277 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11278 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11282 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11283 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11285 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11286 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11290 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11291 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11293 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11294 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11298 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11299 ULONG helpStringContext
)
11301 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11303 TRACE("%p %u\n", This
, helpStringContext
);
11305 This
->dwHelpStringContext
= helpStringContext
;
11310 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11311 UINT index
, ULONG helpStringContext
)
11313 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11314 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11318 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11319 UINT index
, ULONG helpStringContext
)
11321 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11322 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11326 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11328 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11329 FIXME("%p - stub\n", This
);
11333 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11336 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11338 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11341 return E_INVALIDARG
;
11343 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11348 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11349 ICreateTypeInfo2_fnQueryInterface
,
11350 ICreateTypeInfo2_fnAddRef
,
11351 ICreateTypeInfo2_fnRelease
,
11352 ICreateTypeInfo2_fnSetGuid
,
11353 ICreateTypeInfo2_fnSetTypeFlags
,
11354 ICreateTypeInfo2_fnSetDocString
,
11355 ICreateTypeInfo2_fnSetHelpContext
,
11356 ICreateTypeInfo2_fnSetVersion
,
11357 ICreateTypeInfo2_fnAddRefTypeInfo
,
11358 ICreateTypeInfo2_fnAddFuncDesc
,
11359 ICreateTypeInfo2_fnAddImplType
,
11360 ICreateTypeInfo2_fnSetImplTypeFlags
,
11361 ICreateTypeInfo2_fnSetAlignment
,
11362 ICreateTypeInfo2_fnSetSchema
,
11363 ICreateTypeInfo2_fnAddVarDesc
,
11364 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11365 ICreateTypeInfo2_fnSetVarName
,
11366 ICreateTypeInfo2_fnSetTypeDescAlias
,
11367 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11368 ICreateTypeInfo2_fnSetFuncDocString
,
11369 ICreateTypeInfo2_fnSetVarDocString
,
11370 ICreateTypeInfo2_fnSetFuncHelpContext
,
11371 ICreateTypeInfo2_fnSetVarHelpContext
,
11372 ICreateTypeInfo2_fnSetMops
,
11373 ICreateTypeInfo2_fnSetTypeIdldesc
,
11374 ICreateTypeInfo2_fnLayOut
,
11375 ICreateTypeInfo2_fnDeleteFuncDesc
,
11376 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11377 ICreateTypeInfo2_fnDeleteVarDesc
,
11378 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11379 ICreateTypeInfo2_fnDeleteImplType
,
11380 ICreateTypeInfo2_fnSetCustData
,
11381 ICreateTypeInfo2_fnSetFuncCustData
,
11382 ICreateTypeInfo2_fnSetParamCustData
,
11383 ICreateTypeInfo2_fnSetVarCustData
,
11384 ICreateTypeInfo2_fnSetImplTypeCustData
,
11385 ICreateTypeInfo2_fnSetHelpStringContext
,
11386 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11387 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11388 ICreateTypeInfo2_fnInvalidate
,
11389 ICreateTypeInfo2_fnSetName
11392 /******************************************************************************
11393 * ClearCustData (OLEAUT32.171)
11395 * Clear a custom data type's data.
11398 * lpCust [I] The custom data type instance
11403 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11405 if (lpCust
&& lpCust
->cCustData
)
11407 if (lpCust
->prgCustData
)
11411 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11412 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11414 CoTaskMemFree(lpCust
->prgCustData
);
11415 lpCust
->prgCustData
= NULL
;
11417 lpCust
->cCustData
= 0;