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
57 #define NONAMELESSUNION
70 #include "wine/debug.h"
73 #include "wine/heap.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
91 WORD type_id
; /* Type identifier */
92 WORD count
; /* Number of resources of this type */
93 DWORD resloader
; /* SetResourceHandler() */
99 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
100 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
101 static void TLB_FreeVarDesc(VARDESC
*);
103 /****************************************************************************
106 * Takes p_iVal (which is in little endian) and returns it
107 * in the host machine's byte order.
109 #ifdef WORDS_BIGENDIAN
110 static WORD
FromLEWord(WORD p_iVal
)
112 return (((p_iVal
& 0x00FF) << 8) |
113 ((p_iVal
& 0xFF00) >> 8));
117 static DWORD
FromLEDWord(DWORD p_iVal
)
119 return (((p_iVal
& 0x000000FF) << 24) |
120 ((p_iVal
& 0x0000FF00) << 8) |
121 ((p_iVal
& 0x00FF0000) >> 8) |
122 ((p_iVal
& 0xFF000000) >> 24));
125 #define FromLEWord(X) (X)
126 #define FromLEDWord(X) (X)
129 #define DISPATCH_HREF_OFFSET 0x01000000
130 #define DISPATCH_HREF_MASK 0xff000000
132 /****************************************************************************
135 * Fix byte order in any structure if necessary
137 #ifdef WORDS_BIGENDIAN
138 static void FromLEWords(void *p_Val
, int p_iSize
)
142 p_iSize
/= sizeof(WORD
);
145 *Val
= FromLEWord(*Val
);
152 static void FromLEDWords(void *p_Val
, int p_iSize
)
156 p_iSize
/= sizeof(DWORD
);
159 *Val
= FromLEDWord(*Val
);
165 #define FromLEWords(X,Y) /*nothing*/
166 #define FromLEDWords(X,Y) /*nothing*/
170 * Find a typelib key which matches a requested maj.min version.
172 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
177 INT best_maj
= -1, best_min
= -1;
180 lstrcpyW( buffer
, L
"Typelib\\" );
181 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
186 len
= sizeof(key_name
);
188 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
192 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
196 if (*wMaj
== 0xffff && *wMin
== 0xffff)
198 if (v_maj
> best_maj
) best_maj
= v_maj
;
199 if (v_min
> best_min
) best_min
= v_min
;
201 else if (*wMaj
== v_maj
)
208 break; /* exact match */
210 if (*wMin
!= 0xffff && v_min
>= *wMin
&& v_min
> best_min
) best_min
= v_min
;
213 len
= sizeof(key_name
);
217 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
219 if (*wMaj
== 0xffff && *wMin
== 0xffff)
221 if (best_maj
>= 0 && best_min
>= 0)
229 if (*wMaj
== best_maj
&& best_min
>= 0)
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
241 lstrcpyW( buffer
, L
"Typelib\\" );
242 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
243 swprintf( buffer
+ lstrlenW(buffer
), 20, L
"\\%x.%x", wMaj
, wMin
);
247 /* get the path of an interface key, in the form "Interface\\<guid>" */
248 /* buffer must be at least 50 characters long */
249 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
251 lstrcpyW( buffer
, L
"Interface\\" );
252 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
256 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
257 /* buffer must be at least 16 characters long */
258 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
260 swprintf( buffer
, 16, L
"%lx\\", lcid
);
263 case SYS_WIN16
: lstrcatW( buffer
, L
"win16" ); break;
264 case SYS_WIN32
: lstrcatW( buffer
, L
"win32" ); break;
265 case SYS_WIN64
: lstrcatW( buffer
, L
"win64" ); break;
267 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
273 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
275 struct tlibredirect_data
289 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
290 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
291 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
293 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
297 WCHAR Path
[MAX_PATH
];
300 TRACE_(typelib
)("%s, %x.%x, %#lx, %p\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
304 ACTCTX_SECTION_KEYED_DATA data
;
306 data
.cbSize
= sizeof(data
);
307 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
309 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
313 if ((wMaj
!= 0xffff || wMin
!= 0xffff) && (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
))
314 return TYPE_E_LIBNOTREGISTERED
;
316 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
317 len
= SearchPathW( NULL
, nameW
, NULL
, ARRAY_SIZE( Path
), Path
, NULL
);
318 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
320 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
321 *path
= SysAllocString( Path
);
326 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
327 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
329 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
330 if (res
== ERROR_FILE_NOT_FOUND
)
332 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
333 return TYPE_E_LIBNOTREGISTERED
;
335 else if (res
!= ERROR_SUCCESS
)
337 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
338 return TYPE_E_REGISTRYACCESS
;
343 LONG dwPathLen
= sizeof(Path
);
345 get_lcid_subkey( myLCID
, syskind
, buffer
);
347 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
351 else if (myLCID
== lcid
)
353 /* try with sub-langid */
354 myLCID
= SUBLANGID(lcid
);
356 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
358 /* try with system langid */
368 *path
= SysAllocString( Path
);
373 TRACE_(typelib
)("-- %#lx\n", hr
);
377 /****************************************************************************
378 * QueryPathOfRegTypeLib [OLEAUT32.164]
380 * Gets the path to a registered type library.
383 * guid [I] referenced guid
384 * wMaj [I] major version
385 * wMin [I] minor version
387 * path [O] path of typelib
391 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
392 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
395 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
399 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
404 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
407 /******************************************************************************
408 * CreateTypeLib [OLEAUT32.160] creates a typelib
414 HRESULT WINAPI
CreateTypeLib(
415 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
417 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
421 /******************************************************************************
422 * LoadTypeLib [OLEAUT32.161]
424 * Loads a type library
427 * szFile [I] Name of file to load from.
428 * pptLib [O] Pointer that receives ITypeLib object on success.
435 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
437 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
439 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
440 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
443 /******************************************************************************
444 * LoadTypeLibEx [OLEAUT32.183]
446 * Loads and optionally registers a type library
452 HRESULT WINAPI
LoadTypeLibEx(
453 LPCOLESTR szFile
, /* [in] Name of file to load from */
454 REGKIND regkind
, /* [in] Specify kind of registration */
455 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
457 WCHAR szPath
[MAX_PATH
+1];
460 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
462 if (!szFile
|| !pptLib
)
467 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
472 case REGKIND_DEFAULT
:
473 /* don't register typelibs supplied with full path. Experimentation confirms the following */
474 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
475 (szFile
[0] && (szFile
[1] == ':'))) break;
476 /* else fall-through */
478 case REGKIND_REGISTER
:
479 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
481 ITypeLib_Release(*pptLib
);
489 TRACE(" returns %#lx\n",res
);
493 /******************************************************************************
494 * LoadRegTypeLib [OLEAUT32.162]
496 * Loads a registered type library.
499 * rguid [I] GUID of the registered type library.
500 * wVerMajor [I] major version.
501 * wVerMinor [I] minor version.
502 * lcid [I] locale ID.
503 * ppTLib [O] pointer that receives an ITypeLib object on success.
507 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
510 HRESULT WINAPI
LoadRegTypeLib(
522 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
526 res
= LoadTypeLib(bstr
, ppTLib
);
529 if ((wVerMajor
!=0xffff || wVerMinor
!=0xffff) && *ppTLib
)
533 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
536 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
537 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
541 ITypeLib_Release(*ppTLib
);
543 res
= TYPE_E_LIBNOTREGISTERED
;
549 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
554 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
559 get_interface_key( &tattr
->guid
, keyName
);
560 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
561 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
563 const WCHAR
*proxy_clsid
;
565 if (tattr
->typekind
== TKIND_INTERFACE
|| (tattr
->wTypeFlags
& TYPEFLAG_FDUAL
))
566 proxy_clsid
= L
"{00020424-0000-0000-C000-000000000046}";
568 proxy_clsid
= L
"{00020420-0000-0000-C000-000000000046}";
571 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
572 (BYTE
*)name
, (lstrlenW(name
)+1) * sizeof(OLECHAR
));
574 if (!RegCreateKeyExW(key
, L
"ProxyStubClsid", 0, NULL
, 0, KEY_WRITE
| flag
, NULL
, &subKey
, NULL
))
576 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
, (const BYTE
*)proxy_clsid
, (lstrlenW(proxy_clsid
) + 1) * sizeof(WCHAR
));
580 if (!RegCreateKeyExW(key
, L
"ProxyStubClsid32", 0, NULL
, 0, KEY_WRITE
| flag
, NULL
, &subKey
, NULL
))
582 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
, (const BYTE
*)proxy_clsid
, (lstrlenW(proxy_clsid
) + 1) * sizeof(WCHAR
));
586 if (RegCreateKeyExW(key
, L
"TypeLib", 0, NULL
, 0,
587 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
591 StringFromGUID2(&libattr
->guid
, buffer
, 40);
592 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
593 (BYTE
*)buffer
, (lstrlenW(buffer
)+1) * sizeof(WCHAR
));
594 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%x.%x", libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
595 RegSetValueExW(subKey
, L
"Version", 0, REG_SZ
, (BYTE
*)buffer
, (lstrlenW(buffer
)+1) * sizeof(WCHAR
));
603 /******************************************************************************
604 * RegisterTypeLib [OLEAUT32.163]
605 * Adds information about a type library to the System Registry
607 * Docs: ITypeLib FAR * ptlib
608 * Docs: OLECHAR FAR* szFullPath
609 * Docs: OLECHAR FAR* szHelpDir
615 HRESULT WINAPI
RegisterTypeLib(ITypeLib
*ptlib
, const WCHAR
*szFullPath
, const WCHAR
*szHelpDir
)
626 if (ptlib
== NULL
|| szFullPath
== NULL
)
629 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
632 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
635 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
636 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
641 /* Set the human-readable name of the typelib to
642 the typelib's doc, if it exists, else to the typelib's name. */
643 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, &libName
, &doc
, NULL
, NULL
)))
645 else if (doc
|| libName
)
647 WCHAR
*name
= doc
? doc
: libName
;
649 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
650 (BYTE
*)name
, (lstrlenW(name
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
654 SysFreeString(libName
);
657 /* Make up the name of the typelib path subkey */
658 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
660 /* Create the typelib path subkey */
661 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
662 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
664 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
665 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
673 /* Create the flags subkey */
674 if (res
== S_OK
&& RegCreateKeyExW(key
, L
"FLAGS", 0, NULL
, 0,
675 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
679 /* FIXME: is %u correct? */
680 swprintf(buf
, ARRAY_SIZE(buf
), L
"%u", attr
->wLibFlags
);
681 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
682 (BYTE
*)buf
, (lstrlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
690 /* create the helpdir subkey */
691 if (res
== S_OK
&& RegCreateKeyExW(key
, L
"HELPDIR", 0, NULL
, 0,
692 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
694 BSTR freeHelpDir
= NULL
;
697 /* if we created a new key, and helpDir was null, set the helpdir
698 to the directory which contains the typelib. However,
699 if we just opened an existing key, we leave the helpdir alone */
700 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
701 szHelpDir
= freeHelpDir
= SysAllocString(szFullPath
);
702 file_name
= wcsrchr(szHelpDir
, '\\');
703 if (file_name
&& file_name
[1]) {
704 /* possible remove a numeric \index (resource-id) */
705 WCHAR
*end_ptr
= file_name
+ 1;
706 while ('0' <= *end_ptr
&& *end_ptr
<= '9') end_ptr
++;
710 file_name
= wcsrchr(szHelpDir
, '\\');
717 /* if we have an szHelpDir, set it! */
718 if (szHelpDir
!= NULL
) {
719 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
720 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
725 SysFreeString(freeHelpDir
);
736 /* register OLE Automation-compatible interfaces for this typelib */
737 types
= ITypeLib_GetTypeInfoCount(ptlib
);
738 for (tidx
=0; tidx
<types
; tidx
++) {
739 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
740 LPOLESTR name
= NULL
;
741 ITypeInfo
*tinfo
= NULL
;
743 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
746 case TKIND_INTERFACE
:
747 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
748 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
752 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
753 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
757 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
762 TYPEATTR
*tattr
= NULL
;
763 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
766 TRACE_(typelib
)("guid=%s, flags=%04x (",
767 debugstr_guid(&tattr
->guid
),
770 if (TRACE_ON(typelib
)) {
771 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
791 /* Register all dispinterfaces (which includes dual interfaces) and
792 oleautomation interfaces */
793 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
794 kind
== TKIND_DISPATCH
)
797 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
799 /* register interface<->typelib coupling */
800 TLB_register_interface(attr
, name
, tattr
, 0);
802 /* register TLBs into the opposite registry view, too */
803 if(opposite
== KEY_WOW64_32KEY
||
804 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
805 TLB_register_interface(attr
, name
, tattr
, opposite
);
808 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
811 ITypeInfo_Release(tinfo
);
818 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
823 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
825 WCHAR subKeyName
[50];
828 /* the path to the type */
829 get_interface_key( guid
, subKeyName
);
831 /* Delete its bits */
832 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
835 RegDeleteKeyW(subKey
, L
"ProxyStubClsid");
836 RegDeleteKeyW(subKey
, L
"ProxyStubClsid32");
837 RegDeleteKeyW(subKey
, L
"TypeLib");
839 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
842 /******************************************************************************
843 * UnRegisterTypeLib [OLEAUT32.186]
844 * Removes information about a type library from the System Registry
851 HRESULT WINAPI
UnRegisterTypeLib(
852 REFGUID libid
, /* [in] Guid of the library */
853 WORD wVerMajor
, /* [in] major version */
854 WORD wVerMinor
, /* [in] minor version */
855 LCID lcid
, /* [in] locale id */
858 BSTR tlibPath
= NULL
;
861 WCHAR subKeyName
[50];
864 BOOL deleteOtherStuff
;
866 TYPEATTR
* typeAttr
= NULL
;
868 ITypeInfo
* typeInfo
= NULL
;
869 ITypeLib
* typeLib
= NULL
;
872 TRACE("(IID: %s)\n",debugstr_guid(libid
));
874 /* Create the path to the key */
875 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
877 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
879 TRACE("Unsupported syskind %i\n", syskind
);
880 result
= E_INVALIDARG
;
884 /* get the path to the typelib on disk */
885 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
886 result
= E_INVALIDARG
;
890 /* Try and open the key to the type library. */
891 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
892 result
= E_INVALIDARG
;
896 /* Try and load the type library */
897 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
898 result
= TYPE_E_INVALIDSTATE
;
902 /* remove any types registered with this typelib */
903 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
904 for (i
=0; i
<numTypes
; i
++) {
905 /* get the kind of type */
906 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
910 /* skip non-interfaces, and get type info for the type */
911 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
914 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
917 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
921 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
922 kind
== TKIND_DISPATCH
)
925 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
927 TLB_unregister_interface(&typeAttr
->guid
, 0);
929 /* unregister TLBs into the opposite registry view, too */
930 if(opposite
== KEY_WOW64_32KEY
||
931 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
932 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
937 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
939 if (typeInfo
) ITypeInfo_Release(typeInfo
);
943 /* Now, delete the type library path subkey */
944 get_lcid_subkey( lcid
, syskind
, subKeyName
);
945 RegDeleteKeyW(key
, subKeyName
);
946 *wcsrchr( subKeyName
, '\\' ) = 0; /* remove last path component */
947 RegDeleteKeyW(key
, subKeyName
);
949 /* check if there is anything besides the FLAGS/HELPDIR keys.
950 If there is, we don't delete them */
951 tmpLength
= ARRAY_SIZE(subKeyName
);
952 deleteOtherStuff
= TRUE
;
954 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
955 tmpLength
= ARRAY_SIZE(subKeyName
);
957 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
958 if (!wcscmp(subKeyName
, L
"FLAGS")) continue;
959 if (!wcscmp(subKeyName
, L
"HELPDIR")) continue;
960 deleteOtherStuff
= FALSE
;
964 /* only delete the other parts of the key if we're absolutely sure */
965 if (deleteOtherStuff
) {
966 RegDeleteKeyW(key
, L
"FLAGS");
967 RegDeleteKeyW(key
, L
"HELPDIR");
971 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
972 *wcsrchr( keyName
, '\\' ) = 0; /* remove last path component */
973 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
977 SysFreeString(tlibPath
);
978 if (typeLib
) ITypeLib_Release(typeLib
);
979 if (key
) RegCloseKey(key
);
983 /******************************************************************************
984 * RegisterTypeLibForUser [OLEAUT32.442]
985 * Adds information about a type library to the user registry
987 * Docs: ITypeLib FAR * ptlib
988 * Docs: OLECHAR FAR* szFullPath
989 * Docs: OLECHAR FAR* szHelpDir
995 HRESULT WINAPI
RegisterTypeLibForUser(
996 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
997 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
998 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1001 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1002 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1003 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1006 /******************************************************************************
1007 * UnRegisterTypeLibForUser [OLEAUT32.443]
1008 * Removes information about a type library from the user registry
1014 HRESULT WINAPI
UnRegisterTypeLibForUser(
1015 REFGUID libid
, /* [in] GUID of the library */
1016 WORD wVerMajor
, /* [in] major version */
1017 WORD wVerMinor
, /* [in] minor version */
1018 LCID lcid
, /* [in] locale id */
1021 FIXME("%s, %u, %u, %#lx, %u unregistering the typelib system-wide\n",
1022 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1023 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1026 /*======================= ITypeLib implementation =======================*/
1028 typedef struct tagTLBGuid
{
1035 typedef struct tagTLBCustData
1042 /* data structure for import typelibs */
1043 typedef struct tagTLBImpLib
1045 int offset
; /* offset in the file (MSFT)
1046 offset in nametable (SLTG)
1047 just used to identify library while reading
1049 TLBGuid
*guid
; /* libid */
1050 BSTR name
; /* name */
1052 LCID lcid
; /* lcid of imported typelib */
1054 WORD wVersionMajor
; /* major version number */
1055 WORD wVersionMinor
; /* minor version number */
1057 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1058 NULL if not yet loaded */
1062 typedef struct tagTLBString
{
1068 /* internal ITypeLib data */
1069 typedef struct tagITypeLibImpl
1071 ITypeLib2 ITypeLib2_iface
;
1072 ITypeComp ITypeComp_iface
;
1073 ICreateTypeLib2 ICreateTypeLib2_iface
;
1084 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1085 * exported to the application as a UNICODE string.
1087 struct list string_list
;
1088 struct list name_list
;
1089 struct list guid_list
;
1091 const TLBString
*Name
;
1092 const TLBString
*DocString
;
1093 const TLBString
*HelpFile
;
1094 const TLBString
*HelpStringDll
;
1095 DWORD dwHelpContext
;
1096 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1097 struct tagITypeInfoImpl
**typeinfos
;
1098 struct list custdata_list
;
1099 struct list implib_list
;
1100 int ctTypeDesc
; /* number of items in type desc array */
1101 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1102 library. Only used while reading MSFT
1104 struct list ref_list
; /* list of ref types in this typelib */
1105 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1108 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1114 static const ITypeLib2Vtbl tlbvt
;
1115 static const ITypeCompVtbl tlbtcvt
;
1116 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1118 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1120 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1123 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1125 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1128 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1130 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1133 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1135 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1138 /* ITypeLib methods */
1139 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1140 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1142 /*======================= ITypeInfo implementation =======================*/
1144 /* data for referenced types */
1145 typedef struct tagTLBRefType
1147 INT index
; /* Type index for internal ref or for external ref
1148 it the format is SLTG. -2 indicates to
1152 TLBGuid
*guid
; /* guid of the referenced type */
1153 /* if index == TLB_REF_USE_GUID */
1155 HREFTYPE reference
; /* The href of this ref */
1156 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1157 TLB_REF_INTERNAL for internal refs
1158 TLB_REF_NOT_FOUND for broken refs */
1163 #define TLB_REF_USE_GUID -2
1165 #define TLB_REF_INTERNAL (void*)-2
1166 #define TLB_REF_NOT_FOUND (void*)-1
1168 /* internal Parameter data */
1169 typedef struct tagTLBParDesc
1171 const TLBString
*Name
;
1172 struct list custdata_list
;
1175 /* internal Function data */
1176 typedef struct tagTLBFuncDesc
1178 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1179 const TLBString
*Name
; /* the name of this function */
1180 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1182 int HelpStringContext
;
1183 const TLBString
*HelpString
;
1184 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1185 struct list custdata_list
;
1188 /* internal Variable data */
1189 typedef struct tagTLBVarDesc
1191 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1192 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1193 const TLBString
*Name
; /* the name of this variable */
1195 int HelpStringContext
;
1196 const TLBString
*HelpString
;
1197 struct list custdata_list
;
1200 /* internal implemented interface data */
1201 typedef struct tagTLBImplType
1203 HREFTYPE hRef
; /* hRef of interface */
1204 int implflags
; /* IMPLFLAG_*s */
1205 struct list custdata_list
;
1208 /* internal TypeInfo data */
1209 typedef struct tagITypeInfoImpl
1211 ITypeInfo2 ITypeInfo2_iface
;
1212 ITypeComp ITypeComp_iface
;
1213 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1215 BOOL not_attached_to_typelib
;
1220 TYPEDESC
*tdescAlias
;
1222 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1223 int index
; /* index in this typelib; */
1224 HREFTYPE hreftype
; /* hreftype for app object binding */
1225 /* type libs seem to store the doc strings in ascii
1226 * so why should we do it in unicode?
1228 const TLBString
*Name
;
1229 const TLBString
*DocString
;
1230 const TLBString
*DllName
;
1231 const TLBString
*Schema
;
1232 DWORD dwHelpContext
;
1233 DWORD dwHelpStringContext
;
1236 TLBFuncDesc
*funcdescs
;
1239 TLBVarDesc
*vardescs
;
1241 /* Implemented Interfaces */
1242 TLBImplType
*impltypes
;
1244 struct list
*pcustdata_list
;
1245 struct list custdata_list
;
1248 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1250 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1253 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1255 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1258 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1260 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1263 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1265 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1268 static const ITypeInfo2Vtbl tinfvt
;
1269 static const ITypeCompVtbl tcompvt
;
1270 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1272 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1273 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1275 typedef struct tagTLBContext
1277 unsigned int oStart
; /* start of TLB in file */
1278 unsigned int pos
; /* current pos */
1279 unsigned int length
; /* total length */
1280 void *mapping
; /* memory mapping */
1281 MSFT_SegDir
* pTblDir
;
1282 ITypeLibImpl
* pLibInfo
;
1286 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1288 return str
!= NULL
? str
->str
: NULL
;
1291 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1295 return memcmp(left
, str
->str
, len
);
1298 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1300 return guid
!= NULL
? &guid
->guid
: NULL
;
1303 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1305 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1308 static int get_ptr_size(SYSKIND syskind
)
1318 WARN("Unhandled syskind: 0x%x\n", syskind
);
1325 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1326 if (pTD
->vt
& VT_RESERVED
)
1327 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1328 if (pTD
->vt
& VT_BYREF
)
1329 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1330 if (pTD
->vt
& VT_ARRAY
)
1331 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1332 if (pTD
->vt
& VT_VECTOR
)
1333 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1334 switch(pTD
->vt
& VT_TYPEMASK
) {
1335 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1336 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1337 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1338 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1339 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1340 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1341 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1342 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1343 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1344 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1345 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1346 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1347 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1348 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1349 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1350 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1351 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1352 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1353 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1354 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1355 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx", pTD
->u
.hreftype
); break;
1356 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1357 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1358 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1359 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1361 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1362 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1364 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1365 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1366 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1369 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1373 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1375 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1376 dump_TypeDesc(&edesc
->tdesc
,buf
);
1377 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1378 MESSAGE("\t\tu.paramdesc.wParamFlags");
1379 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1380 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1381 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1382 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1383 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1384 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1385 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1386 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1387 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1389 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1391 MESSAGE("memid is %#lx\n", funcdesc
->memid
);
1392 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1393 MESSAGE("Param %d:\n",i
);
1394 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1396 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1397 switch (funcdesc
->funckind
) {
1398 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1399 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1400 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1401 case FUNC_STATIC
: MESSAGE("static");break;
1402 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1403 default: MESSAGE("unknown");break;
1405 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1406 switch (funcdesc
->invkind
) {
1407 case INVOKE_FUNC
: MESSAGE("func");break;
1408 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1409 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1410 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1412 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1413 switch (funcdesc
->callconv
) {
1414 case CC_CDECL
: MESSAGE("cdecl");break;
1415 case CC_PASCAL
: MESSAGE("pascal");break;
1416 case CC_STDCALL
: MESSAGE("stdcall");break;
1417 case CC_SYSCALL
: MESSAGE("syscall");break;
1420 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1421 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1422 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1424 MESSAGE("\telemdescFunc (return value type):\n");
1425 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1428 static const char * const typekind_desc
[] =
1441 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1444 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1445 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1446 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1449 dump_FUNCDESC(&(pfd
->funcdesc
));
1451 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1452 if(pfd
->Entry
== NULL
)
1453 MESSAGE("\tentry: (null)\n");
1454 else if(pfd
->Entry
== (void*)-1)
1455 MESSAGE("\tentry: invalid\n");
1456 else if(IS_INTRESOURCE(pfd
->Entry
))
1457 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1459 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1461 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1465 dump_TLBFuncDescOne(pfd
);
1470 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1474 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1480 static void dump_TLBImpLib(const TLBImpLib
*import
)
1482 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1483 debugstr_w(import
->name
));
1484 TRACE_(typelib
)("v%d.%d lcid %#lx offset=%x\n", import
->wVersionMajor
, import
->wVersionMinor
, import
->lcid
, import
->offset
);
1487 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1491 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1493 TRACE_(typelib
)("href:%#lx\n", ref
->reference
);
1494 if(ref
->index
== -1)
1495 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1497 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1499 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1501 TRACE_(typelib
)("in lib\n");
1502 dump_TLBImpLib(ref
->pImpTLInfo
);
1507 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1512 TRACE_(typelib
)("implementing/inheriting interface hRef = %lx implflags %x\n",
1513 impl
->hRef
, impl
->implflags
);
1519 static void dump_DispParms(const DISPPARAMS
* pdp
)
1523 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1525 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1527 TRACE("named args:\n");
1528 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1529 TRACE( "\t0x%lx\n", pdp
->rgdispidNamedArgs
[index
] );
1532 if (pdp
->cArgs
&& pdp
->rgvarg
)
1535 for (index
= 0; index
< pdp
->cArgs
; index
++)
1536 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1540 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1542 TRACE("%p ref %lu\n", pty
, pty
->ref
);
1543 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1544 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1545 TRACE("kind:%s\n", typekind_desc
[pty
->typeattr
.typekind
]);
1546 TRACE("fct:%u var:%u impl:%u\n", pty
->typeattr
.cFuncs
, pty
->typeattr
.cVars
, pty
->typeattr
.cImplTypes
);
1547 TRACE("wTypeFlags: 0x%04x\n", pty
->typeattr
.wTypeFlags
);
1548 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1549 if (pty
->typeattr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1551 dump_TLBFuncDesc(pty
->funcdescs
, pty
->typeattr
.cFuncs
);
1552 dump_TLBVarDesc(pty
->vardescs
, pty
->typeattr
.cVars
);
1553 dump_TLBImplType(pty
->impltypes
, pty
->typeattr
.cImplTypes
);
1556 static void dump_VARDESC(const VARDESC
*v
)
1558 MESSAGE("memid %ld\n",v
->memid
);
1559 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1560 MESSAGE("oInst %ld\n", v
->u
.oInst
);
1561 dump_ELEMDESC(&(v
->elemdescVar
));
1562 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1563 MESSAGE("varkind %d\n",v
->varkind
);
1566 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1568 /* VT_LPWSTR is largest type that, may appear in type description */
1569 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1570 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1571 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1572 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1573 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1574 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1575 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1576 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1579 static void TLB_abort(void)
1584 /* returns the size required for a deep copy of a typedesc into a
1586 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1590 if (alloc_initial_space
)
1591 size
+= sizeof(TYPEDESC
);
1597 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1600 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1601 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1607 /* deep copy a typedesc into a flat buffer */
1608 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1613 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1622 dest
->u
.lptdesc
= buffer
;
1623 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1626 dest
->u
.lpadesc
= buffer
;
1627 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1628 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1629 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1635 /* free custom data allocated by MSFT_CustData */
1636 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1638 TLBCustData
*cd
, *cdn
;
1639 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1641 list_remove(&cd
->entry
);
1642 VariantClear(&cd
->data
);
1647 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1652 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1653 ret
= SysAllocStringLen(NULL
, len
- 1);
1654 if (!ret
) return ret
;
1655 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1659 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(ITypeInfoImpl
*typeinfo
, MEMBERID memid
)
1663 for (i
= 0; i
< typeinfo
->typeattr
.cFuncs
; ++i
)
1665 if (typeinfo
->funcdescs
[i
].funcdesc
.memid
== memid
)
1666 return &typeinfo
->funcdescs
[i
];
1672 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid_invkind(ITypeInfoImpl
*typeinfo
, MEMBERID memid
, INVOKEKIND invkind
)
1676 for (i
= 0; i
< typeinfo
->typeattr
.cFuncs
; ++i
)
1678 if (typeinfo
->funcdescs
[i
].funcdesc
.memid
== memid
&& typeinfo
->funcdescs
[i
].funcdesc
.invkind
== invkind
)
1679 return &typeinfo
->funcdescs
[i
];
1685 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(ITypeInfoImpl
*typeinfo
, MEMBERID memid
)
1689 for (i
= 0; i
< typeinfo
->typeattr
.cVars
; ++i
)
1691 if (typeinfo
->vardescs
[i
].vardesc
.memid
== memid
)
1692 return &typeinfo
->vardescs
[i
];
1698 static inline TLBVarDesc
*TLB_get_vardesc_by_name(ITypeInfoImpl
*typeinfo
, const OLECHAR
*name
)
1702 for (i
= 0; i
< typeinfo
->typeattr
.cVars
; ++i
)
1704 if (!lstrcmpiW(TLB_get_bstr(typeinfo
->vardescs
[i
].Name
), name
))
1705 return &typeinfo
->vardescs
[i
];
1711 static inline TLBCustData
*TLB_get_custdata_by_guid(const struct list
*custdata_list
, REFGUID guid
)
1713 TLBCustData
*cust_data
;
1714 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1715 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1720 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeLibImpl
*typelib
, const OLECHAR
*name
)
1724 for (i
= 0; i
< typelib
->TypeInfoCount
; ++i
)
1726 if (!lstrcmpiW(TLB_get_bstr(typelib
->typeinfos
[i
]->Name
), name
))
1727 return typelib
->typeinfos
[i
];
1733 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1735 list_init(&var_desc
->custdata_list
);
1738 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1742 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1747 TLBVarDesc_Constructor(&ret
[n
-1]);
1754 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1758 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1763 list_init(&ret
[n
-1].custdata_list
);
1770 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1772 list_init(&func_desc
->custdata_list
);
1775 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1779 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1784 TLBFuncDesc_Constructor(&ret
[n
-1]);
1791 static void TLBImplType_Constructor(TLBImplType
*impl
)
1793 list_init(&impl
->custdata_list
);
1796 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1800 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1805 TLBImplType_Constructor(&ret
[n
-1]);
1812 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1813 const GUID
*new_guid
, HREFTYPE hreftype
)
1817 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1818 if (IsEqualGUID(&guid
->guid
, new_guid
))
1822 guid
= heap_alloc(sizeof(TLBGuid
));
1826 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1827 guid
->hreftype
= hreftype
;
1829 list_add_tail(guid_list
, &guid
->entry
);
1834 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1836 TLBCustData
*cust_data
;
1848 return DISP_E_BADVARTYPE
;
1851 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1854 cust_data
= heap_alloc(sizeof(TLBCustData
));
1856 return E_OUTOFMEMORY
;
1858 cust_data
->guid
= tlbguid
;
1859 VariantInit(&cust_data
->data
);
1861 list_add_tail(custdata_list
, &cust_data
->entry
);
1863 VariantClear(&cust_data
->data
);
1865 return VariantCopy(&cust_data
->data
, var
);
1868 /* Used to update list pointers after list itself was moved. */
1869 static void TLB_relink_custdata(struct list
*custdata_list
)
1871 if (custdata_list
->prev
== custdata_list
->next
)
1872 list_init(custdata_list
);
1875 custdata_list
->prev
->next
= custdata_list
;
1876 custdata_list
->next
->prev
= custdata_list
;
1880 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1887 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1888 if (wcscmp(str
->str
, new_str
) == 0)
1892 str
= heap_alloc(sizeof(TLBString
));
1896 str
->str
= SysAllocString(new_str
);
1902 list_add_tail(string_list
, &str
->entry
);
1907 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1908 ULONG
*size
, WORD
*align
)
1914 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1918 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1920 ITypeInfo_Release(other
);
1925 *size
= attr
->cbSizeInstance
;
1927 *align
= attr
->cbAlignment
;
1929 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1930 ITypeInfo_Release(other
);
1935 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1936 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1938 ULONG i
, sub
, ptr_size
;
1941 ptr_size
= get_ptr_size(sys
);
1980 *size
= sizeof(DATE
);
1983 *size
= sizeof(VARIANT
);
1985 if(sys
== SYS_WIN32
)
1986 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1990 *size
= sizeof(DECIMAL
);
1997 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
1998 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
1999 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2004 case VT_USERDEFINED
:
2005 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2007 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2021 /**********************************************************************
2023 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2026 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2028 if (where
!= DO_NOT_SEEK
)
2030 where
+= pcx
->oStart
;
2031 if (where
> pcx
->length
)
2034 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
2042 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2044 TRACE_(typelib
)("pos=0x%08x len %#lx, %u, %u, %#lx\n",
2045 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2047 MSFT_Seek(pcx
, where
);
2048 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2049 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2054 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2059 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2060 FromLEDWords(buffer
, ret
);
2065 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2070 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2071 FromLEWords(buffer
, ret
);
2076 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2079 MSFT_GuidEntry entry
;
2082 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2084 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2087 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2089 guid
= heap_alloc(sizeof(TLBGuid
));
2091 guid
->offset
= offs
;
2092 guid
->guid
= entry
.guid
;
2093 guid
->hreftype
= entry
.hreftype
;
2095 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2097 offs
+= sizeof(MSFT_GuidEntry
);
2101 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2105 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2106 if(ret
->offset
== offset
){
2107 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2115 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2117 MSFT_NameIntro niName
;
2121 ERR_(typelib
)("bad offset %d\n", offset
);
2125 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2126 pcx
->pTblDir
->pNametab
.offset
+offset
);
2128 return niName
.hreftype
;
2131 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2134 MSFT_NameIntro intro
;
2136 int offs
= 0, lengthInChars
;
2138 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2142 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2145 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2146 intro
.namelen
&= 0xFF;
2147 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2149 len_piece
= (len_piece
+ 4) & ~0x3;
2153 string
= heap_alloc(len_piece
+ 1);
2154 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2155 string
[intro
.namelen
] = '\0';
2157 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2158 string
, -1, NULL
, 0);
2159 if (!lengthInChars
) {
2161 return E_UNEXPECTED
;
2164 tlbstr
= heap_alloc(sizeof(TLBString
));
2166 tlbstr
->offset
= offs
;
2167 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2168 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2172 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2178 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2182 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2183 if (tlbstr
->offset
== offset
) {
2184 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2192 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2196 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2197 if (tlbstr
->offset
== offset
) {
2198 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2207 * read a value and fill a VARIANT structure
2209 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2213 TRACE_(typelib
)("\n");
2215 if(offset
<0) { /* data are packed in here */
2216 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2217 V_I4(pVar
) = offset
& 0x3ffffff;
2220 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2221 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2222 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2223 switch (V_VT(pVar
)){
2224 case VT_EMPTY
: /* FIXME: is this right? */
2225 case VT_NULL
: /* FIXME: is this right? */
2226 case VT_I2
: /* this should not happen */
2237 case VT_VOID
: /* FIXME: is this right? */
2245 case VT_DECIMAL
: /* FIXME: is this right? */
2248 /* pointer types with known behaviour */
2251 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2253 V_BSTR(pVar
) = NULL
;
2255 ptr
= heap_alloc_zero(size
);
2256 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2257 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2258 /* FIXME: do we need a AtoW conversion here? */
2259 V_UNION(pVar
, bstrVal
[size
])='\0';
2260 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2265 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2272 case VT_USERDEFINED
:
2278 case VT_STREAMED_OBJECT
:
2279 case VT_STORED_OBJECT
:
2280 case VT_BLOB_OBJECT
:
2285 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2289 if(size
>0) /* (big|small) endian correct? */
2290 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2294 * create a linked list with custom data
2296 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2302 TRACE_(typelib
)("\n");
2304 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2308 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2309 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2310 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2311 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2312 list_add_head(custdata_list
, &pNew
->entry
);
2313 offset
= entry
.next
;
2318 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2321 pTd
->vt
=type
& VT_TYPEMASK
;
2323 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2325 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2328 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2330 return (invkind
== INVOKE_PROPERTYGET
||
2331 invkind
== INVOKE_PROPERTYPUT
||
2332 invkind
== INVOKE_PROPERTYPUTREF
);
2336 MSFT_DoFuncs(TLBContext
* pcx
,
2341 TLBFuncDesc
** pptfd
)
2344 * member information is stored in a data structure at offset
2345 * indicated by the memoffset field of the typeinfo structure
2346 * There are several distinctive parts.
2347 * The first part starts with a field that holds the total length
2348 * of this (first) part excluding this field. Then follow the records,
2349 * for each member there is one record.
2351 * The first entry is always the length of the record (including this
2353 * The rest of the record depends on the type of the member. If there is
2354 * a field indicating the member type (function, variable, interface, etc)
2355 * I have not found it yet. At this time we depend on the information
2356 * in the type info and the usual order how things are stored.
2358 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2361 * Third is an equal sized array with file offsets to the name entry
2364 * The fourth and last (?) part is an array with offsets to the records
2365 * in the first part of this file segment.
2368 int infolen
, nameoffset
, reclength
, i
;
2369 int recoffset
= offset
+ sizeof(INT
);
2371 char *recbuf
= heap_alloc(0xffff);
2372 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2373 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2375 TRACE_(typelib
)("\n");
2377 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2379 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2381 for ( i
= 0; i
< cFuncs
; i
++ )
2385 /* name, eventually add to a hash table */
2386 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2387 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2389 /* read the function information record */
2390 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2392 reclength
&= 0xffff;
2394 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2396 /* size without argument data */
2397 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2398 if (pFuncRec
->FKCCIC
& 0x1000)
2399 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2401 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2402 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2404 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2405 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2407 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2409 if (pFuncRec
->FKCCIC
& 0x2000 )
2411 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2412 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2413 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2416 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2419 ptfd
->Entry
= (TLBString
*)-1;
2421 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2422 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2424 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2425 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2427 /* fill the FuncDesc Structure */
2428 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2429 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2431 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2432 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2433 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2434 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2435 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2436 if (ptfd
->funcdesc
.funckind
== FUNC_DISPATCH
)
2437 ptfd
->funcdesc
.oVft
= 0;
2439 ptfd
->funcdesc
.oVft
= (pFuncRec
->VtableOffset
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
2440 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2442 /* nameoffset is sometimes -1 on the second half of a propget/propput
2443 * pair of functions */
2444 if ((nameoffset
== -1) && (i
> 0) &&
2445 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2446 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2447 ptfd
->Name
= ptfd_prev
->Name
;
2449 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2453 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2455 /* do the parameters/arguments */
2456 if(pFuncRec
->nrargs
)
2459 MSFT_ParameterInfo paraminfo
;
2461 ptfd
->funcdesc
.lprgelemdescParam
=
2462 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2464 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2466 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2467 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2469 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2471 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2477 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2480 if (paraminfo
.oName
!= -1)
2481 ptfd
->pParamDesc
[j
].Name
=
2482 MSFT_ReadName( pcx
, paraminfo
.oName
);
2483 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2486 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2487 (pFuncRec
->FKCCIC
& 0x1000) )
2489 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2491 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2493 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2495 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2496 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2498 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2502 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2505 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2506 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2507 pFuncRec
->FKCCIC
& 0x80 )
2510 pFuncRec
->oArgCustData
[j
],
2511 &ptfd
->pParamDesc
[j
].custdata_list
);
2514 /* SEEK value = jump to offset,
2515 * from there jump to the end of record,
2516 * go back by (j-1) arguments
2518 MSFT_ReadLEDWords( ¶minfo
,
2519 sizeof(MSFT_ParameterInfo
), pcx
,
2520 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2521 * sizeof(MSFT_ParameterInfo
)));
2525 /* scode is not used: archaic win16 stuff FIXME: right? */
2526 ptfd
->funcdesc
.cScodes
= 0 ;
2527 ptfd
->funcdesc
.lprgscode
= NULL
;
2531 recoffset
+= reclength
;
2536 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2537 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2539 int infolen
, nameoffset
, reclength
;
2541 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2546 TRACE_(typelib
)("\n");
2548 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2549 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2550 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2551 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2552 recoffset
+= offset
+sizeof(INT
);
2553 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2554 /* name, eventually add to a hash table */
2555 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2556 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2557 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2558 /* read the variable information record */
2559 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2561 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2564 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2565 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2567 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2568 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2570 if (reclength
> FIELD_OFFSET(MSFT_VarRecord
, oCustData
))
2571 MSFT_CustData(pcx
, pVarRec
->oCustData
, &ptvd
->custdata_list
);
2573 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2574 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2576 /* fill the VarDesc Structure */
2577 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2578 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2579 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2580 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2581 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2582 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2583 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2584 if(pVarRec
->VarKind
== VAR_CONST
){
2585 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2586 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2587 pVarRec
->OffsValue
, pcx
);
2589 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2590 recoffset
+= reclength
;
2594 /* process Implemented Interfaces of a com class */
2595 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2599 MSFT_RefRecord refrec
;
2602 TRACE_(typelib
)("\n");
2604 pTI
->impltypes
= TLBImplType_Alloc(count
);
2605 pImpl
= pTI
->impltypes
;
2606 for(i
=0;i
<count
;i
++){
2607 if(offset
<0) break; /* paranoia */
2608 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2609 pImpl
->hRef
= refrec
.reftype
;
2610 pImpl
->implflags
=refrec
.flags
;
2611 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2612 offset
=refrec
.onext
;
2618 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2619 * and some structures, and fix the alignment */
2620 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2622 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2623 switch(info
->tdescAlias
->vt
){
2631 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2632 info
->typeattr
.cbAlignment
= sizeof(void*);
2635 case VT_USERDEFINED
:
2636 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2639 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2640 info
->typeattr
.cbAlignment
= 8;
2642 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2643 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2645 info
->typeattr
.cbAlignment
= sizeof(void*);
2648 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2649 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2650 info
->typeattr
.typekind
== TKIND_COCLASS
){
2651 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2652 info
->typeattr
.cbAlignment
= sizeof(void*);
2658 * process a typeinfo record
2660 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2663 ITypeLibImpl
* pLibInfo
)
2665 MSFT_TypeInfoBase tiBase
;
2666 ITypeInfoImpl
*ptiRet
;
2668 TRACE_(typelib
)("count=%u\n", count
);
2670 ptiRet
= ITypeInfoImpl_Constructor();
2671 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2672 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2674 /* this is where we are coming from */
2675 ptiRet
->pTypeLib
= pLibInfo
;
2676 ptiRet
->index
=count
;
2678 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2679 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2680 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2681 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2682 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2683 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2684 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2685 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2686 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2687 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2688 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2689 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2690 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
;
2691 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2693 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2694 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2695 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2699 /* IDLDESC idldescType; *//* never saw this one != zero */
2701 /* name, eventually add to a hash table */
2702 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2703 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2704 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2706 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2707 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2708 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2710 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2711 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2713 /* note: InfoType's Help file and HelpStringDll come from the containing
2714 * library. Further HelpString and Docstring appear to be the same thing :(
2717 if(ptiRet
->typeattr
.cFuncs
>0 )
2718 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2719 ptiRet
->typeattr
.cVars
,
2720 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2722 if(ptiRet
->typeattr
.cVars
>0 )
2723 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2724 ptiRet
->typeattr
.cVars
,
2725 tiBase
.memoffset
, &ptiRet
->vardescs
);
2726 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2727 switch(ptiRet
->typeattr
.typekind
)
2730 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2733 case TKIND_DISPATCH
:
2734 /* This is not -1 when the interface is a non-base dual interface or
2735 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2736 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2740 if (tiBase
.datatype1
!= -1)
2742 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2743 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2747 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2748 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2752 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2754 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2755 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2756 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2757 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2758 if (TRACE_ON(typelib
))
2759 dump_TypeInfo(ptiRet
);
2764 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2767 INT16 len_str
, len_piece
;
2768 int offs
= 0, lengthInChars
;
2770 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2774 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2777 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2778 len_piece
= len_str
+ sizeof(INT16
);
2780 len_piece
= (len_piece
+ 4) & ~0x3;
2784 string
= heap_alloc(len_piece
+ 1);
2785 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2786 string
[len_str
] = '\0';
2788 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2789 string
, -1, NULL
, 0);
2790 if (!lengthInChars
) {
2792 return E_UNEXPECTED
;
2795 tlbstr
= heap_alloc(sizeof(TLBString
));
2797 tlbstr
->offset
= offs
;
2798 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2799 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2803 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2809 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2814 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2815 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2816 MSFT_ImpInfo impinfo
;
2819 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2821 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2822 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2824 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2825 if(pImpLib
->offset
==impinfo
.oImpFile
)
2828 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2829 ref
->reference
= offs
;
2830 ref
->pImpTLInfo
= pImpLib
;
2831 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2832 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2833 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2834 ref
->index
= TLB_REF_USE_GUID
;
2836 ref
->index
= impinfo
.oGuid
;
2838 ERR("Cannot find a reference\n");
2839 ref
->reference
= -1;
2840 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2843 offs
+= sizeof(impinfo
);
2849 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2850 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2851 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2854 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2855 static CRITICAL_SECTION cache_section
;
2856 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2858 0, 0, &cache_section
,
2859 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2860 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2862 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2865 typedef struct TLB_PEFile
2867 IUnknown IUnknown_iface
;
2870 HRSRC typelib_resource
;
2871 HGLOBAL typelib_global
;
2872 LPVOID typelib_base
;
2875 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2877 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2880 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2882 if (IsEqualIID(riid
, &IID_IUnknown
))
2885 IUnknown_AddRef(iface
);
2889 return E_NOINTERFACE
;
2892 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2894 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2895 return InterlockedIncrement(&This
->refs
);
2898 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2900 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2901 ULONG refs
= InterlockedDecrement(&This
->refs
);
2904 if (This
->typelib_global
)
2905 FreeResource(This
->typelib_global
);
2907 FreeLibrary(This
->dll
);
2913 static const IUnknownVtbl TLB_PEFile_Vtable
=
2915 TLB_PEFile_QueryInterface
,
2920 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2923 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2925 This
= heap_alloc(sizeof(TLB_PEFile
));
2927 return E_OUTOFMEMORY
;
2929 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2932 This
->typelib_resource
= NULL
;
2933 This
->typelib_global
= NULL
;
2934 This
->typelib_base
= NULL
;
2936 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2937 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2941 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), L
"TYPELIB");
2942 if (This
->typelib_resource
)
2944 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2945 if (This
->typelib_global
)
2947 This
->typelib_base
= LockResource(This
->typelib_global
);
2949 if (This
->typelib_base
)
2951 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2952 *ppBase
= This
->typelib_base
;
2953 *ppFile
= &This
->IUnknown_iface
;
2959 TRACE("No TYPELIB resource found\n");
2963 TLB_PEFile_Release(&This
->IUnknown_iface
);
2967 typedef struct TLB_NEFile
2969 IUnknown IUnknown_iface
;
2971 LPVOID typelib_base
;
2974 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2976 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2979 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2981 if (IsEqualIID(riid
, &IID_IUnknown
))
2984 IUnknown_AddRef(iface
);
2988 return E_NOINTERFACE
;
2991 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2993 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2994 return InterlockedIncrement(&This
->refs
);
2997 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2999 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3000 ULONG refs
= InterlockedDecrement(&This
->refs
);
3003 heap_free(This
->typelib_base
);
3009 static const IUnknownVtbl TLB_NEFile_Vtable
=
3011 TLB_NEFile_QueryInterface
,
3016 /***********************************************************************
3017 * read_xx_header [internal]
3019 static int read_xx_header( HFILE lzfd
)
3021 IMAGE_DOS_HEADER mzh
;
3024 LZSeek( lzfd
, 0, SEEK_SET
);
3025 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3027 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3030 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3031 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3034 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3036 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3037 return IMAGE_OS2_SIGNATURE
;
3038 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3039 return IMAGE_NT_SIGNATURE
;
3042 WARN("Can't handle %s files.\n", magic
);
3047 /***********************************************************************
3048 * find_ne_resource [internal]
3050 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3051 DWORD
*resLen
, DWORD
*resOff
)
3053 IMAGE_OS2_HEADER nehd
;
3054 NE_TYPEINFO
*typeInfo
;
3055 NE_NAMEINFO
*nameInfo
;
3061 /* Read in NE header */
3062 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3063 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3065 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3068 TRACE("No resources in NE dll\n" );
3072 /* Read in resource table */
3073 resTab
= heap_alloc( resTabSize
);
3074 if ( !resTab
) return FALSE
;
3076 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3077 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3079 heap_free( resTab
);
3084 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3086 if (!IS_INTRESOURCE(typeid)) /* named type */
3088 BYTE len
= strlen( typeid );
3089 while (typeInfo
->type_id
)
3091 if (!(typeInfo
->type_id
& 0x8000))
3093 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3094 if ((*p
== len
) && !_strnicmp( (char*)p
+1, typeid, len
)) goto found_type
;
3096 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3097 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3100 else /* numeric type id */
3102 WORD id
= LOWORD(typeid) | 0x8000;
3103 while (typeInfo
->type_id
)
3105 if (typeInfo
->type_id
== id
) goto found_type
;
3106 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3107 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3110 TRACE("No typeid entry found for %p\n", typeid );
3111 heap_free( resTab
);
3115 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3117 if (!IS_INTRESOURCE(resid
)) /* named resource */
3119 BYTE len
= strlen( resid
);
3120 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3122 BYTE
*p
= resTab
+ nameInfo
->id
;
3123 if (nameInfo
->id
& 0x8000) continue;
3124 if ((*p
== len
) && !_strnicmp( (char*)p
+1, resid
, len
)) goto found_name
;
3127 else /* numeric resource id */
3129 WORD id
= LOWORD(resid
) | 0x8000;
3130 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3131 if (nameInfo
->id
== id
) goto found_name
;
3133 TRACE("No resid entry found for %p\n", typeid );
3134 heap_free( resTab
);
3138 /* Return resource data */
3139 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3140 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3142 heap_free( resTab
);
3146 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3150 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3153 This
= heap_alloc(sizeof(TLB_NEFile
));
3154 if (!This
) return E_OUTOFMEMORY
;
3156 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3158 This
->typelib_base
= NULL
;
3160 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3161 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3163 DWORD reslen
, offset
;
3164 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3166 This
->typelib_base
= heap_alloc(reslen
);
3167 if( !This
->typelib_base
)
3171 LZSeek( lzfd
, offset
, SEEK_SET
);
3172 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3174 *ppBase
= This
->typelib_base
;
3175 *pdwTLBLength
= reslen
;
3176 *ppFile
= &This
->IUnknown_iface
;
3182 if( lzfd
>= 0) LZClose( lzfd
);
3183 TLB_NEFile_Release(&This
->IUnknown_iface
);
3187 typedef struct TLB_Mapping
3189 IUnknown IUnknown_iface
;
3193 LPVOID typelib_base
;
3196 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3198 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3201 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3203 if (IsEqualIID(riid
, &IID_IUnknown
))
3206 IUnknown_AddRef(iface
);
3210 return E_NOINTERFACE
;
3213 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3215 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3216 return InterlockedIncrement(&This
->refs
);
3219 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3221 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3222 ULONG refs
= InterlockedDecrement(&This
->refs
);
3225 if (This
->typelib_base
)
3226 UnmapViewOfFile(This
->typelib_base
);
3228 CloseHandle(This
->mapping
);
3229 if (This
->file
!= INVALID_HANDLE_VALUE
)
3230 CloseHandle(This
->file
);
3236 static const IUnknownVtbl TLB_Mapping_Vtable
=
3238 TLB_Mapping_QueryInterface
,
3243 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3247 This
= heap_alloc(sizeof(TLB_Mapping
));
3249 return E_OUTOFMEMORY
;
3251 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3253 This
->file
= INVALID_HANDLE_VALUE
;
3254 This
->mapping
= NULL
;
3255 This
->typelib_base
= NULL
;
3257 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3258 if (INVALID_HANDLE_VALUE
!= This
->file
)
3260 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3263 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3264 if(This
->typelib_base
)
3266 /* retrieve file size */
3267 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3268 *ppBase
= This
->typelib_base
;
3269 *ppFile
= &This
->IUnknown_iface
;
3275 IUnknown_Release(&This
->IUnknown_iface
);
3276 return TYPE_E_CANTLOADLIBRARY
;
3279 /****************************************************************************
3282 * find the type of the typelib file and map the typelib resource into
3286 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3287 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3289 ITypeLibImpl
*entry
;
3292 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3293 LPVOID pBase
= NULL
;
3294 DWORD dwTLBLength
= 0;
3295 IUnknown
*pFile
= NULL
;
3300 index_str
= wcsrchr(pszFileName
, '\\');
3301 if(index_str
&& *++index_str
!= '\0')
3304 LONG idx
= wcstol(index_str
, &end_ptr
, 10);
3305 if(*end_ptr
== '\0')
3307 int str_len
= index_str
- pszFileName
- 1;
3309 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3310 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3315 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3317 if(wcschr(file
, '\\'))
3319 lstrcpyW(pszPath
, file
);
3323 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3324 pszPath
[len
] = '\\';
3325 memcpy(pszPath
+ len
+ 1, file
, (lstrlenW(file
) + 1) * sizeof(WCHAR
));
3329 if(file
!= pszFileName
) heap_free(file
);
3331 h
= CreateFileW(pszPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3332 if(h
!= INVALID_HANDLE_VALUE
){
3333 GetFinalPathNameByHandleW(h
, pszPath
, cchPath
, FILE_NAME_NORMALIZED
| VOLUME_NAME_DOS
);
3337 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3339 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3340 EnterCriticalSection(&cache_section
);
3341 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3343 if (!wcsicmp(entry
->path
, pszPath
) && entry
->index
== index
)
3345 TRACE("cache hit\n");
3346 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3347 ITypeLib2_AddRef(*ppTypeLib
);
3348 LeaveCriticalSection(&cache_section
);
3352 LeaveCriticalSection(&cache_section
);
3354 /* now actually load and parse the typelib */
3356 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3357 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3358 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3359 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3360 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3363 if (dwTLBLength
>= 4)
3365 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3366 if (dwSignature
== MSFT_SIGNATURE
)
3367 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3368 else if (dwSignature
== SLTG_SIGNATURE
)
3369 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3372 FIXME("Header type magic %#lx not supported.\n", dwSignature
);
3373 ret
= TYPE_E_CANTLOADLIBRARY
;
3377 ret
= TYPE_E_CANTLOADLIBRARY
;
3378 IUnknown_Release(pFile
);
3382 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3384 TRACE("adding to cache\n");
3385 impl
->path
= heap_alloc((lstrlenW(pszPath
)+1) * sizeof(WCHAR
));
3386 lstrcpyW(impl
->path
, pszPath
);
3387 /* We should really canonicalise the path here. */
3388 impl
->index
= index
;
3390 /* FIXME: check if it has added already in the meantime */
3391 EnterCriticalSection(&cache_section
);
3392 list_add_head(&tlb_cache
, &impl
->entry
);
3393 LeaveCriticalSection(&cache_section
);
3399 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName
), GetLastError());
3401 ret
= TYPE_E_CANTLOADLIBRARY
;
3408 /*================== ITypeLib(2) Methods ===================================*/
3410 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3412 ITypeLibImpl
* pTypeLibImpl
;
3414 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3415 if (!pTypeLibImpl
) return NULL
;
3417 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3418 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3419 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3420 pTypeLibImpl
->ref
= 1;
3422 list_init(&pTypeLibImpl
->implib_list
);
3423 list_init(&pTypeLibImpl
->custdata_list
);
3424 list_init(&pTypeLibImpl
->name_list
);
3425 list_init(&pTypeLibImpl
->string_list
);
3426 list_init(&pTypeLibImpl
->guid_list
);
3427 list_init(&pTypeLibImpl
->ref_list
);
3428 pTypeLibImpl
->dispatch_href
= -1;
3430 return pTypeLibImpl
;
3433 /****************************************************************************
3434 * ITypeLib2_Constructor_MSFT
3436 * loading an MSFT typelib from an in-memory image
3438 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3442 MSFT_Header tlbHeader
;
3443 MSFT_SegDir tlbSegDir
;
3444 ITypeLibImpl
* pTypeLibImpl
;
3447 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
3449 pTypeLibImpl
= TypeLibImpl_Constructor();
3450 if (!pTypeLibImpl
) return NULL
;
3452 /* get pointer to beginning of typelib data */
3456 cx
.pLibInfo
= pTypeLibImpl
;
3457 cx
.length
= dwTLBLength
;
3460 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3461 TRACE_(typelib
)("header:\n");
3462 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3463 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3464 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3467 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3469 /* there is a small amount of information here until the next important
3471 * the segment directory . Try to calculate the amount of data */
3472 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3474 /* now read the segment directory */
3475 TRACE("read segment directory (at %ld)\n",lPSegDir
);
3476 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3477 cx
.pTblDir
= &tlbSegDir
;
3479 /* just check two entries */
3480 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3482 ERR("cannot find the table directory, ptr %#lx\n",lPSegDir
);
3483 heap_free(pTypeLibImpl
);
3487 MSFT_ReadAllNames(&cx
);
3488 MSFT_ReadAllStrings(&cx
);
3489 MSFT_ReadAllGuids(&cx
);
3491 /* now fill our internal data */
3492 /* TLIBATTR fields */
3493 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3495 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3496 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3497 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3498 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3499 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3501 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3502 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3504 /* name, eventually add to a hash table */
3505 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3508 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3509 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3511 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3514 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3515 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3518 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3521 if(tlbHeader
.CustomDataOffset
>= 0)
3523 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3526 /* fill in type descriptions */
3527 if(tlbSegDir
.pTypdescTab
.length
> 0)
3529 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3531 pTypeLibImpl
->ctTypeDesc
= cTD
;
3532 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3533 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3536 /* FIXME: add several sanity checks here */
3537 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3538 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3540 /* FIXME: check safearray */
3542 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3544 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3546 else if(td
[0] == VT_CARRAY
)
3548 /* array descr table here */
3549 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3551 else if(td
[0] == VT_USERDEFINED
)
3553 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3555 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3558 /* second time around to fill the array subscript info */
3561 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3562 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3564 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3565 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3568 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3570 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3572 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3574 for(j
= 0; j
<td
[2]; j
++)
3576 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3577 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3578 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3579 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3584 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3585 ERR("didn't find array description data\n");
3590 /* imported type libs */
3591 if(tlbSegDir
.pImpFiles
.offset
>0)
3594 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3597 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3601 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3602 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3603 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3605 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3606 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3607 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3608 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3611 name
= heap_alloc_zero(size
+1);
3612 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3613 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3616 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3617 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3619 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3623 MSFT_ReadAllRefs(&cx
);
3625 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3628 if(tlbHeader
.nrtypeinfos
>= 0 )
3630 ITypeInfoImpl
**ppTI
;
3632 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3634 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3636 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3639 (pTypeLibImpl
->TypeInfoCount
)++;
3644 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3645 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3646 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3650 TRACE("(%p)\n", pTypeLibImpl
);
3651 return &pTypeLibImpl
->ITypeLib2_iface
;
3655 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3661 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3662 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3666 guid
->Data4
[0] = s
>> 8;
3667 guid
->Data4
[1] = s
& 0xff;
3670 for(i
= 0; i
< 6; i
++) {
3671 memcpy(b
, str
+ 24 + 2 * i
, 2);
3672 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3677 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3684 bytelen
= *(const WORD
*)ptr
;
3685 if(bytelen
== 0xffff) return 2;
3687 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3688 tmp_str
= SysAllocStringLen(NULL
, len
);
3690 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3691 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3692 SysFreeString(tmp_str
);
3697 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3702 bytelen
= *(const WORD
*)ptr
;
3703 if(bytelen
== 0xffff) return 2;
3704 *str
= heap_alloc(bytelen
+ 1);
3705 memcpy(*str
, ptr
+ 2, bytelen
);
3706 (*str
)[bytelen
] = '\0';
3710 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3715 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3716 if (tlbstr
->offset
== offset
)
3720 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3721 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3722 SysFreeString(tmp_str
);
3727 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3729 char *ptr
= pLibBlk
;
3732 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3733 FIXME("libblk magic = %04x\n", w
);
3738 if((w
= *(WORD
*)ptr
) != 0xffff) {
3739 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w
);
3744 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3746 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3748 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3751 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3752 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3755 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3756 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3758 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3761 ptr
+= 4; /* skip res12 */
3763 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3766 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3769 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3772 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3773 ptr
+= sizeof(GUID
);
3775 return ptr
- (char*)pLibBlk
;
3778 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3783 } sltg_ref_lookup_t
;
3785 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3786 HREFTYPE
*typelib_ref
)
3788 if(table
&& typeinfo_ref
< table
->num
)
3790 *typelib_ref
= table
->refs
[typeinfo_ref
];
3794 ERR_(typelib
)("Unable to find reference\n");
3799 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3804 if((*pType
& 0xe00) == 0xe00) {
3806 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3807 pTD
= pTD
->u
.lptdesc
;
3809 switch(*pType
& 0x3f) {
3812 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3813 pTD
= pTD
->u
.lptdesc
;
3816 case VT_USERDEFINED
:
3817 pTD
->vt
= VT_USERDEFINED
;
3818 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3824 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3827 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3829 pTD
->vt
= VT_CARRAY
;
3830 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3831 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3832 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3833 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3835 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3841 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3845 pTD
->vt
= VT_SAFEARRAY
;
3846 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3847 pTD
= pTD
->u
.lptdesc
;
3851 pTD
->vt
= *pType
& 0x3f;
3860 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3861 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3863 /* Handle [in/out] first */
3864 if((*pType
& 0xc000) == 0xc000)
3865 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3866 else if(*pType
& 0x8000)
3867 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3868 else if(*pType
& 0x4000)
3869 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3871 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3874 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3877 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3879 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3883 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3888 TLBRefType
*ref_type
;
3889 sltg_ref_lookup_t
*table
;
3890 HREFTYPE typelib_ref
;
3892 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3893 FIXME("Ref magic = %x\n", pRef
->magic
);
3896 name
= ( (char*)pRef
->names
+ pRef
->number
);
3898 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3899 table
->num
= pRef
->number
>> 3;
3901 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3903 /* We don't want the first href to be 0 */
3904 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3906 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3908 unsigned int lib_offs
, type_num
;
3910 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3912 name
+= SLTG_ReadStringA(name
, &refname
);
3913 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3914 FIXME_(typelib
)("Can't sscanf ref\n");
3915 if(lib_offs
!= 0xffff) {
3918 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3919 if(import
->offset
== lib_offs
)
3922 if(&import
->entry
== &pTL
->implib_list
) {
3923 char fname
[MAX_PATH
+1];
3927 import
= heap_alloc_zero(sizeof(*import
));
3928 import
->offset
= lib_offs
;
3929 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3930 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3931 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
3932 &import
->wVersionMajor
,
3933 &import
->wVersionMinor
,
3934 &import
->lcid
, fname
) != 4) {
3935 FIXME_(typelib
)("can't sscanf ref %s\n",
3936 pNameTable
+ lib_offs
+ 40);
3938 len
= strlen(fname
);
3939 if(fname
[len
-1] != '#')
3940 FIXME("fname = %s\n", fname
);
3941 fname
[len
-1] = '\0';
3942 import
->name
= TLB_MultiByteToBSTR(fname
);
3943 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3945 ref_type
->pImpTLInfo
= import
;
3947 /* Store a reference to IDispatch */
3948 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3949 pTL
->dispatch_href
= typelib_ref
;
3951 } else { /* internal ref */
3952 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3954 ref_type
->reference
= typelib_ref
;
3955 ref_type
->index
= type_num
;
3958 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3960 table
->refs
[ref
] = typelib_ref
;
3963 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3964 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3965 dump_TLBRefType(pTL
);
3969 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3970 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3972 SLTG_ImplInfo
*info
;
3973 TLBImplType
*pImplType
;
3974 /* I don't really get this structure, usually it's 0x16 bytes
3975 long, but iuser.tlb contains some that are 0x18 bytes long.
3976 That's ok because we can use the next ptr to jump to the next
3977 one. But how do we know the length of the last one? The WORD
3978 at offs 0x8 might be the clue. For now I'm just assuming that
3979 the last one is the regular 0x16 bytes. */
3981 info
= (SLTG_ImplInfo
*)pBlk
;
3983 pTI
->typeattr
.cImplTypes
++;
3984 if(info
->next
== 0xffff)
3986 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3989 info
= (SLTG_ImplInfo
*)pBlk
;
3990 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
3991 pImplType
= pTI
->impltypes
;
3993 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3994 pImplType
->implflags
= info
->impltypeflags
;
3997 if(info
->next
== 0xffff)
4000 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4001 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4003 info
++; /* see comment at top of function */
4007 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4008 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4010 TLBVarDesc
*pVarDesc
;
4011 const TLBString
*prevName
= NULL
;
4012 SLTG_Variable
*pItem
;
4016 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4018 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4019 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4021 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4023 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4024 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4025 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4029 if (pItem
->name
== 0xfffe)
4030 pVarDesc
->Name
= prevName
;
4032 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4034 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4035 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4036 TRACE_(typelib
)("memid = %#lx\n", pItem
->memid
);
4038 if(pItem
->flags
& 0x02)
4039 pType
= &pItem
->type
;
4041 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4043 if (pItem
->flags
& ~0xda)
4044 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4046 SLTG_DoElem(pType
, pBlk
,
4047 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4049 if (TRACE_ON(typelib
)) {
4051 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4052 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4055 if (pItem
->flags
& 0x40) {
4056 TRACE_(typelib
)("VAR_DISPATCH\n");
4057 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4059 else if (pItem
->flags
& 0x10) {
4060 TRACE_(typelib
)("VAR_CONST\n");
4061 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4062 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4063 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4064 if (pItem
->flags
& 0x08)
4065 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4067 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4073 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4075 TRACE_(typelib
)("len = %u\n", len
);
4076 if (len
== 0xffff) {
4079 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4080 str
= SysAllocStringLen(NULL
, alloc_len
);
4081 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4083 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4084 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4093 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4094 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4097 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4102 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4103 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4104 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4107 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4108 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4110 if (pItem
->flags
& 0x80)
4111 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4113 prevName
= pVarDesc
->Name
;
4115 pTI
->typeattr
.cVars
= cVars
;
4118 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4119 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4121 SLTG_Function
*pFunc
;
4123 TLBFuncDesc
*pFuncDesc
;
4125 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4127 pFuncDesc
= pTI
->funcdescs
;
4128 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4129 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4134 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4135 case SLTG_FUNCTION_MAGIC
:
4136 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4138 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4139 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4141 case SLTG_STATIC_FUNCTION_MAGIC
:
4142 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4145 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4148 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4150 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4151 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4152 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4153 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4154 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4155 if (pFuncDesc
->funcdesc
.funckind
== FUNC_DISPATCH
)
4156 pFuncDesc
->funcdesc
.oVft
= 0;
4158 pFuncDesc
->funcdesc
.oVft
= (pFunc
->vtblpos
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
4160 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4161 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4163 if(pFunc
->retnextopt
& 0x80)
4164 pType
= &pFunc
->rettype
;
4166 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4168 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4170 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4171 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4172 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4174 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4176 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4177 char *paramName
= pNameTable
+ *pArg
;
4179 /* If arg type follows then paramName points to the 2nd
4180 letter of the name, else the next WORD is an offset to
4181 the arg type and paramName points to the first letter.
4182 So let's take one char off paramName and see if we're
4183 pointing at an alphanumeric char. However if *pArg is
4184 0xffff or 0xfffe then the param has no name, the former
4185 meaning that the next WORD is the type, the latter
4186 meaning that the next WORD is an offset to the type. */
4191 else if(*pArg
== 0xfffe) {
4195 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4200 if(HaveOffs
) { /* the next word is an offset to type */
4201 pType
= (WORD
*)(pBlk
+ *pArg
);
4202 SLTG_DoElem(pType
, pBlk
,
4203 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4208 pArg
= SLTG_DoElem(pArg
, pBlk
,
4209 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4212 /* Are we an optional param ? */
4213 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4214 pFuncDesc
->funcdesc
.cParamsOpt
)
4215 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4218 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4219 paramName
- pNameTable
, pTI
->pTypeLib
);
4221 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4225 pTI
->typeattr
.cFuncs
= cFuncs
;
4228 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4229 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4230 SLTG_TypeInfoTail
*pTITail
)
4233 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4235 if(pTIHeader
->href_table
!= 0xffffffff) {
4236 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4242 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4243 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4245 heap_free(ref_lookup
);
4249 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4250 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4251 const SLTG_TypeInfoTail
*pTITail
)
4254 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4256 if(pTIHeader
->href_table
!= 0xffffffff) {
4257 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4263 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4264 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4267 if (pTITail
->funcs_off
!= 0xffff)
4268 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4270 heap_free(ref_lookup
);
4272 if (TRACE_ON(typelib
))
4273 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4276 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4277 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4278 const SLTG_TypeInfoTail
*pTITail
)
4280 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4283 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4284 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4285 const SLTG_TypeInfoTail
*pTITail
)
4288 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4290 if (pTITail
->simple_alias
) {
4291 /* if simple alias, no more processing required */
4292 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4293 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4297 if(pTIHeader
->href_table
!= 0xffffffff) {
4298 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4302 /* otherwise it is an offset to a type */
4303 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4305 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4306 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4308 heap_free(ref_lookup
);
4311 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4312 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4313 const SLTG_TypeInfoTail
*pTITail
)
4315 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4316 if (pTIHeader
->href_table
!= 0xffffffff)
4317 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4320 if (pTITail
->vars_off
!= 0xffff)
4321 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4323 if (pTITail
->funcs_off
!= 0xffff)
4324 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4326 if (pTITail
->impls_off
!= 0xffff)
4327 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4329 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4330 * of dispinterface functions including the IDispatch ones, so
4331 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4332 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4334 heap_free(ref_lookup
);
4335 if (TRACE_ON(typelib
))
4336 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4339 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4340 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4341 const SLTG_TypeInfoTail
*pTITail
)
4343 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4346 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4347 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4348 const SLTG_TypeInfoTail
*pTITail
)
4350 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4351 if (pTIHeader
->href_table
!= 0xffffffff)
4352 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4355 if (pTITail
->vars_off
!= 0xffff)
4356 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4358 if (pTITail
->funcs_off
!= 0xffff)
4359 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4360 heap_free(ref_lookup
);
4361 if (TRACE_ON(typelib
))
4365 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4366 manageable copy of it into this */
4379 } SLTG_InternalOtherTypeInfo
;
4381 /****************************************************************************
4382 * ITypeLib2_Constructor_SLTG
4384 * loading a SLTG typelib from an in-memory image
4386 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4388 ITypeLibImpl
*pTypeLibImpl
;
4389 SLTG_Header
*pHeader
;
4390 SLTG_BlkEntry
*pBlkEntry
;
4394 LPVOID pBlk
, pFirstBlk
;
4395 SLTG_LibBlk
*pLibBlk
;
4396 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4397 char *pAfterOTIBlks
= NULL
;
4398 char *pNameTable
, *ptr
;
4401 ITypeInfoImpl
**ppTypeInfoImpl
;
4403 TRACE_(typelib
)("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
4406 pTypeLibImpl
= TypeLibImpl_Constructor();
4407 if (!pTypeLibImpl
) return NULL
;
4411 TRACE_(typelib
)("header:\n");
4412 TRACE_(typelib
)("\tmagic %#lx, file blocks = %d\n", pHeader
->SLTG_magic
,
4413 pHeader
->nrOfFileBlks
);
4414 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
)
4416 FIXME_(typelib
)("Header type magic %#lx not supported.\n", pHeader
->SLTG_magic
);
4420 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4421 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4423 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4424 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4426 /* Next we have a magic block */
4427 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4429 /* Let's see if we're still in sync */
4430 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4431 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4432 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4435 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4436 sizeof(SLTG_DIR_MAGIC
))) {
4437 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4441 pIndex
= (SLTG_Index
*)(pMagic
+1);
4443 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4445 pFirstBlk
= pPad9
+ 1;
4447 /* We'll set up a ptr to the main library block, which is the last one. */
4449 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4450 pBlkEntry
[order
].next
!= 0;
4451 order
= pBlkEntry
[order
].next
- 1) {
4452 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4456 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4458 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4463 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4465 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4468 ptr
= (char*)pLibBlk
+ len
;
4470 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4474 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4476 w
= *(WORD
*)(ptr
+ 2);
4479 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4480 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4481 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4483 w
= *(WORD
*)(ptr
+ 4 + len
);
4485 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4487 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4488 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4489 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4491 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4492 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4493 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4495 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4496 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4499 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4500 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4501 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4502 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4503 len
+= sizeof(SLTG_OtherTypeInfo
);
4507 pAfterOTIBlks
= ptr
;
4509 /* Skip this WORD and get the next DWORD */
4510 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4512 /* Now add this to pLibBLk look at what we're pointing at and
4513 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4514 dust and we should be pointing at the beginning of the name
4517 pNameTable
= (char*)pLibBlk
+ len
;
4519 switch(*(WORD
*)pNameTable
) {
4526 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4530 pNameTable
+= 0x216;
4534 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4536 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4539 /* Hopefully we now have enough ptrs set up to actually read in
4540 some TypeInfos. It's not clear which order to do them in, so
4541 I'll just follow the links along the BlkEntry chain and read
4542 them in the order in which they are in the file */
4544 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4545 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4547 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4548 pBlkEntry
[order
].next
!= 0;
4549 order
= pBlkEntry
[order
].next
- 1, i
++) {
4551 SLTG_TypeInfoHeader
*pTIHeader
;
4552 SLTG_TypeInfoTail
*pTITail
;
4553 SLTG_MemberHeader
*pMemHeader
;
4555 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4556 FIXME_(typelib
)("Index strings don't match\n");
4557 heap_free(pOtherTypeInfoBlks
);
4562 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4563 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4564 heap_free(pOtherTypeInfoBlks
);
4567 TRACE_(typelib
)("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, "
4568 "pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
4569 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4571 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4572 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4573 (*ppTypeInfoImpl
)->index
= i
;
4574 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4575 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4576 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4577 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4578 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4579 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4580 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4581 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4583 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4584 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4586 if((pTIHeader
->typeflags1
& 7) != 2)
4587 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4588 if(pTIHeader
->typeflags3
!= 2)
4589 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4591 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4592 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4593 typekind_desc
[pTIHeader
->typekind
],
4594 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4595 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4597 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4599 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4601 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4602 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4603 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4605 switch(pTIHeader
->typekind
) {
4607 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4608 pTIHeader
, pTITail
);
4612 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4613 pTIHeader
, pTITail
);
4616 case TKIND_INTERFACE
:
4617 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4618 pTIHeader
, pTITail
);
4622 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4623 pTIHeader
, pTITail
);
4627 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4628 pTIHeader
, pTITail
);
4631 case TKIND_DISPATCH
:
4632 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4633 pTIHeader
, pTITail
);
4637 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4638 pTIHeader
, pTITail
);
4642 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4647 /* could get cFuncs, cVars and cImplTypes from here
4648 but we've already set those */
4649 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4665 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4668 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4669 FIXME("Somehow processed %d TypeInfos\n", i
);
4670 heap_free(pOtherTypeInfoBlks
);
4674 heap_free(pOtherTypeInfoBlks
);
4675 return &pTypeLibImpl
->ITypeLib2_iface
;
4678 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4680 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4682 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4684 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4685 IsEqualIID(riid
,&IID_ITypeLib
)||
4686 IsEqualIID(riid
,&IID_ITypeLib2
))
4688 *ppv
= &This
->ITypeLib2_iface
;
4690 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4691 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4693 *ppv
= &This
->ICreateTypeLib2_iface
;
4698 TRACE("-- Interface: E_NOINTERFACE\n");
4699 return E_NOINTERFACE
;
4702 IUnknown_AddRef((IUnknown
*)*ppv
);
4706 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4708 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4709 ULONG ref
= InterlockedIncrement(&This
->ref
);
4711 TRACE("%p, refcount %lu.\n", iface
, ref
);
4716 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4718 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4719 ULONG ref
= InterlockedDecrement(&This
->ref
);
4721 TRACE("%p, refcount %lu.\n", iface
, ref
);
4725 TLBImpLib
*pImpLib
, *pImpLibNext
;
4726 TLBRefType
*ref_type
, *ref_type_next
;
4727 TLBString
*tlbstr
, *tlbstr_next
;
4728 TLBGuid
*tlbguid
, *tlbguid_next
;
4731 /* remove cache entry */
4734 TRACE("removing from cache list\n");
4735 EnterCriticalSection(&cache_section
);
4736 if(This
->entry
.next
)
4737 list_remove(&This
->entry
);
4738 LeaveCriticalSection(&cache_section
);
4739 heap_free(This
->path
);
4741 TRACE(" destroying ITypeLib(%p)\n",This
);
4743 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4744 list_remove(&tlbstr
->entry
);
4745 SysFreeString(tlbstr
->str
);
4749 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4750 list_remove(&tlbstr
->entry
);
4751 SysFreeString(tlbstr
->str
);
4755 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4756 list_remove(&tlbguid
->entry
);
4760 TLB_FreeCustData(&This
->custdata_list
);
4762 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4763 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4764 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4766 heap_free(This
->pTypeDesc
);
4768 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4770 if (pImpLib
->pImpTypeLib
)
4771 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4772 SysFreeString(pImpLib
->name
);
4774 list_remove(&pImpLib
->entry
);
4778 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, ref_type_next
, &This
->ref_list
, TLBRefType
, entry
)
4780 list_remove(&ref_type
->entry
);
4781 heap_free(ref_type
);
4784 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4785 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4786 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4788 heap_free(This
->typeinfos
);
4796 /* ITypeLib::GetTypeInfoCount
4798 * Returns the number of type descriptions in the type library
4800 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4802 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4803 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4804 return This
->TypeInfoCount
;
4807 /* ITypeLib::GetTypeInfo
4809 * retrieves the specified type description in the library.
4811 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4814 ITypeInfo
**ppTInfo
)
4816 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4818 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4821 return E_INVALIDARG
;
4823 if(index
>= This
->TypeInfoCount
)
4824 return TYPE_E_ELEMENTNOTFOUND
;
4826 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4827 ITypeInfo_AddRef(*ppTInfo
);
4833 /* ITypeLibs::GetTypeInfoType
4835 * Retrieves the type of a type description.
4837 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4842 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4844 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4847 return E_INVALIDARG
;
4849 if(index
>= This
->TypeInfoCount
)
4850 return TYPE_E_ELEMENTNOTFOUND
;
4852 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4857 /* ITypeLib::GetTypeInfoOfGuid
4859 * Retrieves the type description that corresponds to the specified GUID.
4862 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4865 ITypeInfo
**ppTInfo
)
4867 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4870 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4872 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4873 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4874 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4875 ITypeInfo_AddRef(*ppTInfo
);
4880 return TYPE_E_ELEMENTNOTFOUND
;
4883 /* ITypeLib::GetLibAttr
4885 * Retrieves the structure that contains the library's attributes.
4888 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4892 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4894 TRACE("(%p, %p)\n", This
, attr
);
4896 if (!attr
) return E_INVALIDARG
;
4898 *attr
= heap_alloc(sizeof(**attr
));
4899 if (!*attr
) return E_OUTOFMEMORY
;
4901 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4902 (*attr
)->lcid
= This
->set_lcid
;
4903 (*attr
)->syskind
= This
->syskind
;
4904 (*attr
)->wMajorVerNum
= This
->ver_major
;
4905 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4906 (*attr
)->wLibFlags
= This
->libflags
;
4911 /* ITypeLib::GetTypeComp
4913 * Enables a client compiler to bind to a library's types, variables,
4914 * constants, and global functions.
4917 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4919 ITypeComp
**ppTComp
)
4921 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4923 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4924 *ppTComp
= &This
->ITypeComp_iface
;
4925 ITypeComp_AddRef(*ppTComp
);
4930 /* ITypeLib::GetDocumentation
4932 * Retrieves the library's documentation string, the complete Help file name
4933 * and path, and the context identifier for the library Help topic in the Help
4936 * On a successful return all non-null BSTR pointers will have been set,
4939 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4943 BSTR
*pBstrDocString
,
4944 DWORD
*pdwHelpContext
,
4945 BSTR
*pBstrHelpFile
)
4947 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4948 HRESULT result
= E_INVALIDARG
;
4951 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4953 pBstrName
, pBstrDocString
,
4954 pdwHelpContext
, pBstrHelpFile
);
4958 /* documentation for the typelib */
4963 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4971 if (This
->DocString
)
4973 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4977 *pBstrDocString
= NULL
;
4981 *pdwHelpContext
= This
->dwHelpContext
;
4987 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
4991 *pBstrHelpFile
= NULL
;
4998 /* for a typeinfo */
4999 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5001 if(SUCCEEDED(result
))
5003 result
= ITypeInfo_GetDocumentation(pTInfo
,
5007 pdwHelpContext
, pBstrHelpFile
);
5009 ITypeInfo_Release(pTInfo
);
5014 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5016 if (pBstrName
) SysFreeString (*pBstrName
);
5018 return STG_E_INSUFFICIENTMEMORY
;
5023 * Indicates whether a passed-in string contains the name of a type or member
5024 * described in the library.
5027 static HRESULT WINAPI
ITypeLib2_fnIsName(
5033 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5035 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5037 TRACE("%p, %s, %#lx, %p.\n", iface
, debugstr_w(szNameBuf
), lHashVal
, pfName
);
5040 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5041 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5042 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5043 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5044 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5046 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5047 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5048 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5049 goto ITypeLib2_fnIsName_exit
;
5052 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5053 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5054 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5060 ITypeLib2_fnIsName_exit
:
5061 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5062 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5067 /* ITypeLib::FindName
5069 * Finds occurrences of a type description in a type library. This may be used
5070 * to quickly verify that a name exists in a type library.
5073 static HRESULT WINAPI
ITypeLib2_fnFindName(
5077 ITypeInfo
**ppTInfo
,
5081 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5086 TRACE("%p, %s %#lx, %p, %p, %p.\n", iface
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5088 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5089 return E_INVALIDARG
;
5091 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5092 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5093 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5097 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5098 memid
[count
] = MEMBERID_NIL
;
5099 goto ITypeLib2_fnFindName_exit
;
5102 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5103 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5105 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5106 memid
[count
] = func
->funcdesc
.memid
;
5107 goto ITypeLib2_fnFindName_exit
;
5111 var
= TLB_get_vardesc_by_name(pTInfo
, name
);
5113 memid
[count
] = var
->vardesc
.memid
;
5114 goto ITypeLib2_fnFindName_exit
;
5118 ITypeLib2_fnFindName_exit
:
5119 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5120 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5123 TRACE("found %d typeinfos\n", count
);
5130 /* ITypeLib::ReleaseTLibAttr
5132 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5135 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5137 TLIBATTR
*pTLibAttr
)
5139 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5140 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5141 heap_free(pTLibAttr
);
5144 /* ITypeLib2::GetCustData
5146 * gets the custom data
5148 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5153 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5154 TLBCustData
*pCData
;
5156 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5158 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5160 return TYPE_E_ELEMENTNOTFOUND
;
5162 VariantInit(pVarVal
);
5163 VariantCopy(pVarVal
, &pCData
->data
);
5168 /* ITypeLib2::GetLibStatistics
5170 * Returns statistics about a type library that are required for efficient
5171 * sizing of hash tables.
5174 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5176 ULONG
*pcUniqueNames
,
5177 ULONG
*pcchUniqueNames
)
5179 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5181 FIXME("(%p): stub!\n", This
);
5183 if(pcUniqueNames
) *pcUniqueNames
=1;
5184 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5188 /* ITypeLib2::GetDocumentation2
5190 * Retrieves the library's documentation string, the complete Help file name
5191 * and path, the localization context to use, and the context ID for the
5192 * library Help topic in the Help file.
5195 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5199 BSTR
*pbstrHelpString
,
5200 DWORD
*pdwHelpStringContext
,
5201 BSTR
*pbstrHelpStringDll
)
5203 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5207 FIXME("%p, %d, %#lx, partially implemented stub!\n", iface
, index
, lcid
);
5209 /* the help string should be obtained from the helpstringdll,
5210 * using the _DLLGetDocumentation function, based on the supplied
5211 * lcid. Nice to do sometime...
5215 /* documentation for the typelib */
5217 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5218 if(pdwHelpStringContext
)
5219 *pdwHelpStringContext
=This
->dwHelpContext
;
5220 if(pbstrHelpStringDll
)
5221 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5227 /* for a typeinfo */
5228 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5230 if(SUCCEEDED(result
))
5232 ITypeInfo2
* pTInfo2
;
5233 result
= ITypeInfo_QueryInterface(pTInfo
,
5235 (LPVOID
*) &pTInfo2
);
5237 if(SUCCEEDED(result
))
5239 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5243 pdwHelpStringContext
,
5244 pbstrHelpStringDll
);
5246 ITypeInfo2_Release(pTInfo2
);
5249 ITypeInfo_Release(pTInfo
);
5255 static HRESULT
TLB_copy_all_custdata(const struct list
*custdata_list
, CUSTDATA
*pCustData
)
5257 TLBCustData
*pCData
;
5262 ct
= list_count(custdata_list
);
5264 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5265 if(!pCustData
->prgCustData
)
5266 return E_OUTOFMEMORY
;
5268 pCustData
->cCustData
= ct
;
5270 cdi
= pCustData
->prgCustData
;
5271 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5272 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5273 VariantInit(&cdi
->varValue
);
5274 hr
= VariantCopy(&cdi
->varValue
, &pCData
->data
);
5275 if(FAILED(hr
)) break;
5283 /* ITypeLib2::GetAllCustData
5285 * Gets all custom data items for the library.
5288 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5290 CUSTDATA
*pCustData
)
5292 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5293 TRACE("(%p)->(%p)\n", This
, pCustData
);
5294 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5297 static const ITypeLib2Vtbl tlbvt
= {
5298 ITypeLib2_fnQueryInterface
,
5300 ITypeLib2_fnRelease
,
5301 ITypeLib2_fnGetTypeInfoCount
,
5302 ITypeLib2_fnGetTypeInfo
,
5303 ITypeLib2_fnGetTypeInfoType
,
5304 ITypeLib2_fnGetTypeInfoOfGuid
,
5305 ITypeLib2_fnGetLibAttr
,
5306 ITypeLib2_fnGetTypeComp
,
5307 ITypeLib2_fnGetDocumentation
,
5309 ITypeLib2_fnFindName
,
5310 ITypeLib2_fnReleaseTLibAttr
,
5312 ITypeLib2_fnGetCustData
,
5313 ITypeLib2_fnGetLibStatistics
,
5314 ITypeLib2_fnGetDocumentation2
,
5315 ITypeLib2_fnGetAllCustData
5319 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5321 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5323 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5326 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5328 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5330 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5333 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5335 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5337 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5340 static HRESULT WINAPI
ITypeLibComp_fnBind(
5345 ITypeInfo
** ppTInfo
,
5346 DESCKIND
* pDescKind
,
5349 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5350 BOOL typemismatch
= FALSE
;
5353 TRACE("%p, %s, %#lx, %#x, %p, %p, %p.\n", iface
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5355 *pDescKind
= DESCKIND_NONE
;
5356 pBindPtr
->lptcomp
= NULL
;
5359 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5360 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5361 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5363 /* FIXME: check wFlags here? */
5364 /* FIXME: we should use a hash table to look this info up using lHash
5365 * instead of an O(n) search */
5366 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5367 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5369 if (pTypeInfo
->Name
&& !wcscmp(pTypeInfo
->Name
->str
, szName
))
5371 *pDescKind
= DESCKIND_TYPECOMP
;
5372 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5373 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5374 TRACE("module or enum: %s\n", debugstr_w(szName
));
5379 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5380 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5382 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5385 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5386 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5388 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5391 else if (hr
== TYPE_E_TYPEMISMATCH
)
5392 typemismatch
= TRUE
;
5395 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5396 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5398 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5400 ITypeInfo
*subtypeinfo
;
5402 DESCKIND subdesckind
;
5404 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5405 &subtypeinfo
, &subdesckind
, &subbindptr
);
5406 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5408 TYPEDESC tdesc_appobject
;
5409 const VARDESC vardesc_appobject
=
5412 NULL
, /* lpstrSchema */
5427 VAR_STATIC
/* varkind */
5430 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5431 tdesc_appobject
.vt
= VT_USERDEFINED
;
5433 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5435 /* cleanup things filled in by Bind call so we can put our
5436 * application object data in there instead */
5437 switch (subdesckind
)
5439 case DESCKIND_FUNCDESC
:
5440 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5442 case DESCKIND_VARDESC
:
5443 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5448 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5450 if (pTypeInfo
->hreftype
== -1)
5451 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5453 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5457 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5458 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5459 ITypeInfo_AddRef(*ppTInfo
);
5462 else if (hr
== TYPE_E_TYPEMISMATCH
)
5463 typemismatch
= TRUE
;
5469 TRACE("type mismatch %s\n", debugstr_w(szName
));
5470 return TYPE_E_TYPEMISMATCH
;
5474 TRACE("name not found %s\n", debugstr_w(szName
));
5479 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5483 ITypeInfo
** ppTInfo
,
5484 ITypeComp
** ppTComp
)
5486 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5487 ITypeInfoImpl
*info
;
5489 TRACE("%p, %s, %#lx, %p, %p.\n", iface
, debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5491 if(!szName
|| !ppTInfo
|| !ppTComp
)
5492 return E_INVALIDARG
;
5494 info
= TLB_get_typeinfo_by_name(This
, szName
);
5501 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5502 ITypeInfo_AddRef(*ppTInfo
);
5503 *ppTComp
= &info
->ITypeComp_iface
;
5504 ITypeComp_AddRef(*ppTComp
);
5509 static const ITypeCompVtbl tlbtcvt
=
5512 ITypeLibComp_fnQueryInterface
,
5513 ITypeLibComp_fnAddRef
,
5514 ITypeLibComp_fnRelease
,
5516 ITypeLibComp_fnBind
,
5517 ITypeLibComp_fnBindType
5520 /*================== ITypeInfo(2) Methods ===================================*/
5521 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5523 ITypeInfoImpl
*pTypeInfoImpl
;
5525 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5528 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5529 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5530 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5531 pTypeInfoImpl
->ref
= 0;
5532 pTypeInfoImpl
->hreftype
= -1;
5533 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5534 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5535 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5536 list_init(pTypeInfoImpl
->pcustdata_list
);
5538 TRACE("(%p)\n", pTypeInfoImpl
);
5539 return pTypeInfoImpl
;
5542 /* ITypeInfo::QueryInterface
5544 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5549 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5551 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5554 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5555 IsEqualIID(riid
,&IID_ITypeInfo
)||
5556 IsEqualIID(riid
,&IID_ITypeInfo2
))
5557 *ppvObject
= &This
->ITypeInfo2_iface
;
5558 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5559 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5560 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5561 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5562 *ppvObject
= &This
->ITypeComp_iface
;
5565 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5566 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5569 TRACE("-- Interface: E_NOINTERFACE\n");
5570 return E_NOINTERFACE
;
5573 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5575 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5576 ULONG ref
= InterlockedIncrement(&This
->ref
);
5578 TRACE("%p, refcount %lu.\n", iface
, ref
);
5580 if (ref
== 1 /* incremented from 0 */)
5581 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5586 static void typeinfo_release_funcdesc(TLBFuncDesc
*func
)
5590 for (i
= 0; i
< func
->funcdesc
.cParams
; ++i
)
5592 ELEMDESC
*elemdesc
= &func
->funcdesc
.lprgelemdescParam
[i
];
5593 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5594 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5595 TLB_FreeCustData(&func
->pParamDesc
[i
].custdata_list
);
5597 heap_free(func
->funcdesc
.lprgelemdescParam
);
5598 heap_free(func
->pParamDesc
);
5599 TLB_FreeCustData(&func
->custdata_list
);
5602 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5606 TRACE("destroying ITypeInfo(%p)\n",This
);
5608 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5610 typeinfo_release_funcdesc(&This
->funcdescs
[i
]);
5612 heap_free(This
->funcdescs
);
5614 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5616 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5617 if (pVInfo
->vardesc_create
) {
5618 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5619 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5620 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5621 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5623 TLB_FreeCustData(&pVInfo
->custdata_list
);
5625 heap_free(This
->vardescs
);
5627 if(This
->impltypes
){
5628 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5629 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5630 TLB_FreeCustData(&pImpl
->custdata_list
);
5632 heap_free(This
->impltypes
);
5635 TLB_FreeCustData(&This
->custdata_list
);
5640 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5642 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5643 ULONG ref
= InterlockedDecrement(&This
->ref
);
5645 TRACE("%p, refcount %lu.\n", iface
, ref
);
5649 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5650 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5651 if (not_attached_to_typelib
)
5653 /* otherwise This will be freed when typelib is freed */
5659 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5660 LPTYPEATTR
*ppTypeAttr
)
5662 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5665 TRACE("(%p)\n",This
);
5667 size
= sizeof(**ppTypeAttr
);
5668 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5669 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5671 *ppTypeAttr
= heap_alloc(size
);
5673 return E_OUTOFMEMORY
;
5675 **ppTypeAttr
= This
->typeattr
;
5676 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5678 if (This
->tdescAlias
)
5679 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5681 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5682 /* This should include all the inherited funcs */
5683 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5684 /* This is always the size of IDispatch's vtbl */
5685 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5686 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5691 /* ITypeInfo::GetTypeComp
5693 * Retrieves the ITypeComp interface for the type description, which enables a
5694 * client compiler to bind to the type description's members.
5697 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5698 ITypeComp
* *ppTComp
)
5700 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5702 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5704 *ppTComp
= &This
->ITypeComp_iface
;
5705 ITypeComp_AddRef(*ppTComp
);
5709 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5711 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5712 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5713 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5717 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5720 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5721 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5723 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5724 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5725 *buffer
+= sizeof(PARAMDESCEX
);
5726 *pparamdescex_dest
= *pparamdescex_src
;
5727 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5728 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5729 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5730 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5733 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5737 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5739 UINT len
= SysStringLen(str
), i
;
5740 for (i
= 0; i
< len
; ++i
)
5746 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5748 if (V_VT(var
) == VT_INT
)
5749 return VariantChangeType(var
, var
, 0, VT_I4
);
5750 else if (V_VT(var
) == VT_UINT
)
5751 return VariantChangeType(var
, var
, 0, VT_UI4
);
5752 else if (V_VT(var
) == VT_BSTR
)
5753 return TLB_SanitizeBSTR(V_BSTR(var
));
5758 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5760 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5761 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5764 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5768 SIZE_T size
= sizeof(*src
);
5772 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5773 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5774 for (i
= 0; i
< src
->cParams
; i
++)
5776 size
+= sizeof(ELEMDESC
);
5777 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5780 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5781 if (!dest
) return E_OUTOFMEMORY
;
5784 if (dispinterface
) /* overwrite funckind */
5785 dest
->funckind
= FUNC_DISPATCH
;
5786 buffer
= (char *)(dest
+ 1);
5788 dest
->oVft
= dest
->oVft
& 0xFFFC;
5790 if (dest
->cScodes
) {
5791 dest
->lprgscode
= (SCODE
*)buffer
;
5792 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5793 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5795 dest
->lprgscode
= NULL
;
5797 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5800 SysFreeString((BSTR
)dest
);
5804 if (dest
->cParams
) {
5805 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5806 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5807 for (i
= 0; i
< src
->cParams
; i
++)
5809 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5815 /* undo the above actions */
5816 for (i
= i
- 1; i
>= 0; i
--)
5817 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5818 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5819 SysFreeString((BSTR
)dest
);
5823 dest
->lprgelemdescParam
= NULL
;
5825 /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
5826 * This accounts for several arguments that are separate in the signature of
5827 * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
5828 if (dispinterface
&& (src
->funckind
!= FUNC_DISPATCH
))
5830 /* functions that have a [retval] parameter return this value into pVarResult.
5831 * [retval] is always the last parameter (if present) */
5832 if (dest
->cParams
&&
5833 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5835 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5836 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5838 ERR("elemdesc should have started with VT_PTR instead of:\n");
5840 dump_ELEMDESC(elemdesc
);
5841 return E_UNEXPECTED
;
5844 /* the type pointed to by this [retval] becomes elemdescFunc,
5845 * i.e. the function signature's return type.
5846 * We are using a flat buffer so there is no danger of leaking memory */
5847 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5849 /* remove the last parameter */
5852 else if (dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5853 /* Even if not otherwise replaced HRESULT is returned in pExcepInfo->scode,
5854 * not pVarResult. So the function signature should show no return value. */
5855 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5857 /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
5858 * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
5859 if (dest
->cParams
&& (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FLCID
))
5867 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5869 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5870 if (var_desc
->varkind
== VAR_CONST
)
5871 VariantClear(var_desc
->u
.lpvarValue
);
5872 SysFreeString((BSTR
)var_desc
);
5875 /* internal function to make the inherited interfaces' methods appear
5876 * part of the interface */
5877 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5878 UINT index
, const TLBFuncDesc
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5880 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5882 UINT implemented_funcs
= 0;
5887 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5891 ITypeInfo
*pSubTypeInfo
;
5894 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5898 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5901 &sub_funcs
, hrefoffset
);
5902 implemented_funcs
+= sub_funcs
;
5903 ITypeInfo_Release(pSubTypeInfo
);
5906 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5910 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5914 if (index
< implemented_funcs
)
5915 return E_INVALIDARG
;
5916 index
-= implemented_funcs
;
5918 if (index
>= This
->typeattr
.cFuncs
)
5919 return TYPE_E_ELEMENTNOTFOUND
;
5921 *ppFuncDesc
= &This
->funcdescs
[index
];
5925 static HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const TLBFuncDesc
**func_desc
, UINT
*hrefoffset
)
5927 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5929 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5930 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface
, index
, func_desc
, NULL
, hrefoffset
);
5932 if (index
>= This
->typeattr
.cFuncs
)
5933 return TYPE_E_ELEMENTNOTFOUND
;
5935 *func_desc
= &This
->funcdescs
[index
];
5939 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5941 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5944 switch (pTypeDesc
->vt
)
5946 case VT_USERDEFINED
:
5947 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5951 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5954 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5962 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5965 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5966 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5967 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5970 /* ITypeInfo::GetFuncDesc
5972 * Retrieves the FUNCDESC structure that contains information about a
5973 * specified function.
5976 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5977 LPFUNCDESC
*ppFuncDesc
)
5979 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5980 const TLBFuncDesc
*internal_funcdesc
;
5982 UINT hrefoffset
= 0;
5984 TRACE("(%p) index %d\n", This
, index
);
5987 return E_INVALIDARG
;
5989 if (This
->needs_layout
)
5990 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5992 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5993 &internal_funcdesc
, &hrefoffset
);
5996 WARN("description for function %d not found\n", index
);
6000 hr
= TLB_AllocAndInitFuncDesc(
6001 &internal_funcdesc
->funcdesc
,
6003 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6005 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
6006 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6008 TRACE("-- %#lx.\n", hr
);
6012 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6016 SIZE_T size
= sizeof(*src
);
6019 if (src
->lpstrSchema
) size
+= (lstrlenW(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
= lstrlenW(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 /* internal function to make the inherited interfaces' methods appear
6088 * part of the interface, remembering if the top-level was dispinterface */
6089 static HRESULT
typeinfo_getnames( ITypeInfo
*iface
, MEMBERID memid
, BSTR
*names
,
6090 UINT max_names
, UINT
*num_names
, BOOL dispinterface
)
6092 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
6093 const TLBFuncDesc
*func_desc
;
6094 const TLBVarDesc
*var_desc
;
6099 func_desc
= TLB_get_funcdesc_by_memberid(This
, memid
);
6102 UINT params
= func_desc
->funcdesc
.cParams
;
6103 if (!max_names
|| !func_desc
->Name
)
6106 *names
= SysAllocString(TLB_get_bstr(func_desc
->Name
));
6109 if (dispinterface
&& (func_desc
->funcdesc
.funckind
!= FUNC_DISPATCH
))
6111 /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc */
6112 if ((params
> 0) && (func_desc
->funcdesc
.lprgelemdescParam
[params
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
6113 --params
; /* Invoke(pVarResult) supplies the [retval] parameter, so it's hidden from DISPPARAMS */
6114 if ((params
> 0) && (func_desc
->funcdesc
.lprgelemdescParam
[params
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FLCID
))
6115 --params
; /* Invoke(lcid) supplies the [lcid] parameter, so it's hidden from DISPPARAMS */
6118 for (i
= 0; i
< params
; i
++)
6120 if (*num_names
>= max_names
|| !func_desc
->pParamDesc
[i
].Name
)
6122 names
[*num_names
] = SysAllocString(TLB_get_bstr(func_desc
->pParamDesc
[i
].Name
));
6128 var_desc
= TLB_get_vardesc_by_memberid(This
, memid
);
6131 *names
= SysAllocString(TLB_get_bstr(var_desc
->Name
));
6136 if (This
->impltypes
&&
6137 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
))
6139 /* recursive search */
6142 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &parent
);
6143 if (SUCCEEDED(result
))
6145 result
= typeinfo_getnames(parent
, memid
, names
, max_names
, num_names
, dispinterface
);
6146 ITypeInfo_Release(parent
);
6149 WARN("Could not search inherited interface!\n");
6153 WARN("no names found\n");
6156 return TYPE_E_ELEMENTNOTFOUND
;
6161 /* ITypeInfo_GetNames
6163 * Retrieves the variable with the specified member ID (or the name of the
6164 * property or method and its parameters) that correspond to the specified
6167 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6168 BSTR
*names
, UINT max_names
, UINT
*num_names
)
6170 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6172 TRACE("%p, %#lx, %p, %d, %p\n", iface
, memid
, names
, max_names
, num_names
);
6174 if (!names
) return E_INVALIDARG
;
6176 return typeinfo_getnames((ITypeInfo
*)iface
, memid
, names
, max_names
, num_names
,
6177 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6180 /* ITypeInfo::GetRefTypeOfImplType
6182 * If a type description describes a COM class, it retrieves the type
6183 * description of the implemented interface types. For an interface,
6184 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6188 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6193 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6196 TRACE("(%p) index %d\n", This
, index
);
6197 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6201 /* only valid on dual interfaces;
6202 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6205 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6211 hr
= TYPE_E_ELEMENTNOTFOUND
;
6214 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6216 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6217 *pRefType
= This
->pTypeLib
->dispatch_href
;
6221 if(index
>= This
->typeattr
.cImplTypes
)
6222 hr
= TYPE_E_ELEMENTNOTFOUND
;
6224 *pRefType
= This
->impltypes
[index
].hRef
;
6225 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6233 TRACE("SUCCESS -- hRef %#lx.\n", *pRefType
);
6235 TRACE("FAILURE -- hresult %#lx.\n", hr
);
6241 /* ITypeInfo::GetImplTypeFlags
6243 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6244 * or base interface in a type description.
6246 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6247 UINT index
, INT
*pImplTypeFlags
)
6249 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6251 TRACE("(%p) index %d\n", This
, index
);
6254 return E_INVALIDARG
;
6256 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6257 *pImplTypeFlags
= 0;
6261 if(index
>= This
->typeattr
.cImplTypes
)
6262 return TYPE_E_ELEMENTNOTFOUND
;
6264 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6270 * Maps between member names and member IDs, and parameter names and
6273 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6274 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6276 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6277 const TLBVarDesc
*pVDesc
;
6281 TRACE("%p, %s, %d.\n", iface
, debugstr_w(*rgszNames
), cNames
);
6283 /* init out parameters in case of failure */
6284 for (i
= 0; i
< cNames
; i
++)
6285 pMemId
[i
] = MEMBERID_NIL
;
6287 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6289 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6290 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6291 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6292 for(i
=1; i
< cNames
; i
++){
6293 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6294 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6296 if( j
<pFDesc
->funcdesc
.cParams
)
6299 ret
=DISP_E_UNKNOWNNAME
;
6301 TRACE("-- %#lx.\n", ret
);
6305 pVDesc
= TLB_get_vardesc_by_name(This
, *rgszNames
);
6308 *pMemId
= pVDesc
->vardesc
.memid
;
6311 /* not found, see if it can be found in an inherited interface */
6312 if(This
->impltypes
) {
6313 /* recursive search */
6315 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6317 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6318 ITypeInfo_Release(pTInfo
);
6321 WARN("Could not search inherited interface!\n");
6323 WARN("no names found\n");
6324 return DISP_E_UNKNOWNNAME
;
6330 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6331 extern double call_double_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6332 __ASM_GLOBAL_FUNC( call_method
,
6334 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6335 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6336 "movl %esp,%ebp\n\t"
6337 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6339 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6341 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6342 "movl 12(%ebp),%edx\n\t"
6343 "movl %esp,%edi\n\t"
6346 "subl %edx,%edi\n\t"
6347 "andl $~15,%edi\n\t"
6348 "movl %edi,%esp\n\t"
6349 "movl 12(%ebp),%ecx\n\t"
6350 "movl 16(%ebp),%esi\n\t"
6353 "1:\tcall *8(%ebp)\n\t"
6354 "subl %esp,%edi\n\t"
6355 "movl 20(%ebp),%ecx\n\t"
6356 "movl %edi,(%ecx)\n\t"
6357 "leal -8(%ebp),%esp\n\t"
6359 __ASM_CFI(".cfi_same_value %edi\n\t")
6361 __ASM_CFI(".cfi_same_value %esi\n\t")
6363 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6364 __ASM_CFI(".cfi_same_value %ebp\n\t")
6366 __ASM_GLOBAL_FUNC( call_double_method
,
6367 "jmp " __ASM_NAME("call_method") )
6369 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6370 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6372 int argspos
= 0, stack_offset
;
6377 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6378 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6379 pvargResult
, V_VT(pvargResult
));
6381 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6383 FIXME("unsupported calling convention %d\n",cc
);
6384 return E_INVALIDARG
;
6387 /* maximum size for an argument is sizeof(VARIANT) */
6388 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6392 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6393 func
= vtable
[oVft
/sizeof(void *)];
6394 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6396 else func
= (void *)oVft
;
6402 args
[argspos
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6405 WARN("invalid return type %u\n", vtReturn
);
6407 return E_INVALIDARG
;
6412 for (i
= 0; i
< cActuals
; i
++)
6414 VARIANT
*arg
= prgpvarg
[i
];
6425 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6426 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6430 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6431 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6433 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6434 args
[argspos
++] = V_BOOL(arg
);
6437 args
[argspos
++] = V_UI4(arg
);
6440 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6448 call_method( func
, argspos
, args
, &stack_offset
);
6451 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6455 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6460 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6463 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6467 if (stack_offset
&& cc
== CC_STDCALL
)
6469 WARN( "stack pointer off by %d\n", stack_offset
);
6470 return DISP_E_BADCALLEE
;
6472 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6473 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6477 #elif defined(__x86_64__)
6479 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6480 extern double CDECL
call_double_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6481 __ASM_GLOBAL_FUNC( call_method
,
6483 __ASM_SEH(".seh_pushreg %rbp\n\t")
6484 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6485 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6486 "movq %rsp,%rbp\n\t"
6487 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6488 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6490 __ASM_SEH(".seh_pushreg %rsi\n\t")
6491 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6493 __ASM_SEH(".seh_pushreg %rdi\n\t")
6494 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6495 __ASM_SEH(".seh_endprologue\n\t")
6496 "movq %rcx,%rax\n\t"
6499 "cmovgq %rdx,%rcx\n\t"
6500 "leaq 0(,%rcx,8),%rdx\n\t"
6501 "subq %rdx,%rsp\n\t"
6502 "andq $~15,%rsp\n\t"
6503 "movq %rsp,%rdi\n\t"
6506 "movq 0(%rsp),%rcx\n\t"
6507 "movq 8(%rsp),%rdx\n\t"
6508 "movq 16(%rsp),%r8\n\t"
6509 "movq 24(%rsp),%r9\n\t"
6510 "movq 0(%rsp),%xmm0\n\t"
6511 "movq 8(%rsp),%xmm1\n\t"
6512 "movq 16(%rsp),%xmm2\n\t"
6513 "movq 24(%rsp),%xmm3\n\t"
6515 "leaq -16(%rbp),%rsp\n\t"
6517 __ASM_CFI(".cfi_same_value %rdi\n\t")
6519 __ASM_CFI(".cfi_same_value %rsi\n\t")
6520 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6522 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6523 __ASM_CFI(".cfi_same_value %rbp\n\t")
6525 __ASM_GLOBAL_FUNC( call_double_method
,
6526 "jmp " __ASM_NAME("call_method") )
6528 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6529 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6536 TRACE("%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d).\n",
6537 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6538 pvargResult
, V_VT(pvargResult
));
6540 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6542 FIXME("unsupported calling convention %d\n",cc
);
6543 return E_INVALIDARG
;
6546 /* maximum size for an argument is sizeof(DWORD_PTR) */
6547 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6551 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6552 func
= vtable
[oVft
/sizeof(void *)];
6553 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6555 else func
= (void *)oVft
;
6561 args
[argspos
++] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6564 WARN("invalid return type %u\n", vtReturn
);
6566 return E_INVALIDARG
;
6571 for (i
= 0; i
< cActuals
; i
++)
6573 VARIANT
*arg
= prgpvarg
[i
];
6579 args
[argspos
++] = (ULONG_PTR
)arg
;
6581 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6582 args
[argspos
++] = V_BOOL(arg
);
6585 args
[argspos
++] = V_UI8(arg
);
6588 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6594 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
);
6598 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
);
6602 call_method( func
, argspos
, args
);
6605 V_UI8(pvargResult
) = call_method( func
, argspos
, args
);
6609 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6610 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6614 #elif defined(__arm__)
6616 extern LONGLONG CDECL
call_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6617 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6618 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6619 __ASM_GLOBAL_FUNC( call_method
,
6622 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6623 * 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)
6626 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6627 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6629 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6630 "beq 1f\n\t" /* Skip allocation if no stack args */
6631 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6632 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6633 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6634 "subs r1, r1, #4\n\t" /* Decrement count */
6635 "bgt 2b\n\t" /* Loop till done */
6639 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6641 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6642 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6644 "blx ip\n\t" /* Call the target function */
6646 "mov sp, fp\n\t" /* Clean the stack using fp */
6647 "pop {fp, pc}\n\t" /* Restore fp and return */
6649 __ASM_GLOBAL_FUNC( call_float_method
,
6650 "b " __ASM_NAME("call_method") )
6651 __ASM_GLOBAL_FUNC( call_double_method
,
6652 "b " __ASM_NAME("call_method") )
6654 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6655 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6670 int rcount
; /* 32-bit register index count */
6672 int scount
= 0; /* single-precision float register index count */
6673 int dcount
= 0; /* double-precision float register index count */
6676 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6677 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6679 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6681 FIXME("unsupported calling convention %d\n",cc
);
6682 return E_INVALIDARG
;
6690 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6691 func
= vtable
[oVft
/sizeof(void *)];
6692 regs
.r
[rcount
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6694 else func
= (void *)oVft
;
6696 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6697 /* first as it will need to be in the 'r' registers: */
6702 regs
.r
[rcount
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6705 WARN("invalid return type %u\n", vtReturn
);
6706 return E_INVALIDARG
;
6707 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6711 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6712 args
= heap_alloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 4 );
6714 for (i
= 0; i
< cActuals
; i
++)
6716 VARIANT
*arg
= prgpvarg
[i
];
6717 DWORD
*pdwarg
= (DWORD
*)(arg
); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6718 int ntemp
; /* Used for counting words split between registers and stack */
6724 case VT_R8
: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6727 dcount
= max( (scount
+ 1) / 2, dcount
);
6730 regs
.sd
.d
[dcount
++] = V_R8(arg
);
6734 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6735 memcpy( &args
[argspos
], &V_R8(arg
), sizeof(V_R8(arg
)) );
6736 argspos
+= sizeof(V_R8(arg
)) / sizeof(DWORD
);
6740 case VT_I8
: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6745 rcount
+= (rcount
% 2); /* align rcount to 8-byte register pair */
6746 memcpy( ®s
.r
[rcount
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6747 rcount
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6751 rcount
= 4; /* Make sure we flag that all 'r' regs are full */
6752 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6753 memcpy( &args
[argspos
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6754 argspos
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6757 case VT_DECIMAL
: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6759 /* 8-byte align 'r' and/or stack: */
6761 rcount
+= (rcount
% 2);
6765 argspos
+= (argspos
% 2);
6767 ntemp
= sizeof(*arg
) / sizeof(DWORD
);
6771 regs
.r
[rcount
++] = *pdwarg
++;
6773 args
[argspos
++] = *pdwarg
++;
6777 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6779 regs
.r
[rcount
++] = V_BOOL(arg
);
6781 args
[argspos
++] = V_BOOL(arg
);
6783 case VT_R4
: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6785 if (!(scount
% 2)) scount
= max( scount
, dcount
* 2 );
6787 regs
.sd
.s
[scount
++] = V_R4(arg
);
6789 args
[argspos
++] = V_UI4(arg
);
6794 regs
.r
[rcount
++] = V_UI4(arg
);
6796 args
[argspos
++] = V_UI4(arg
);
6799 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6802 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 8-byte */
6806 case VT_EMPTY
: /* EMPTY = no return value */
6807 case VT_DECIMAL
: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6809 call_method( func
, argspos
, args
, (DWORD
*)®s
);
6812 V_R4(pvargResult
) = call_float_method( func
, argspos
, args
, (DWORD
*)®s
);
6816 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, (DWORD
*)®s
);
6821 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6824 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6828 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6829 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6833 #elif defined(__aarch64__)
6835 extern DWORD_PTR CDECL
call_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6836 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6837 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6838 __ASM_GLOBAL_FUNC( call_method
,
6839 "stp x29, x30, [sp, #-16]!\n\t"
6841 "sub sp, sp, x1, lsl #3\n\t"
6843 "1:\tsub x1, x1, #1\n\t"
6844 "ldr x4, [x2, x1, lsl #3]\n\t"
6845 "str x4, [sp, x1, lsl #3]\n\t"
6847 "2:\tmov x16, x0\n\t"
6849 "ldp d0, d1, [x9]\n\t"
6850 "ldp d2, d3, [x9, #0x10]\n\t"
6851 "ldp d4, d5, [x9, #0x20]\n\t"
6852 "ldp d6, d7, [x9, #0x30]\n\t"
6853 "ldp x0, x1, [x9, #0x40]\n\t"
6854 "ldp x2, x3, [x9, #0x50]\n\t"
6855 "ldp x4, x5, [x9, #0x60]\n\t"
6856 "ldp x6, x7, [x9, #0x70]\n\t"
6857 "ldr x8, [x9, #0x80]\n\t"
6860 "ldp x29, x30, [sp], #16\n\t"
6862 __ASM_GLOBAL_FUNC( call_float_method
,
6863 "b " __ASM_NAME("call_method") )
6864 __ASM_GLOBAL_FUNC( call_double_method
,
6865 "b " __ASM_NAME("call_method") )
6867 HRESULT WINAPI
DispCallFunc( void *instance
, ULONG_PTR offset
, CALLCONV cc
, VARTYPE ret_type
, UINT count
,
6868 VARTYPE
*types
, VARIANTARG
**vargs
, VARIANT
*result
)
6883 int rcount
; /* 64-bit register index count */
6884 int fpcount
= 0; /* float register index count */
6886 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6887 instance
, offset
, cc
, ret_type
, count
, types
, vargs
, result
, V_VT(result
));
6889 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6891 FIXME("unsupported calling convention %d\n",cc
);
6892 return E_INVALIDARG
;
6900 const FARPROC
*vtable
= *(FARPROC
**)instance
;
6901 func
= vtable
[offset
/sizeof(void *)];
6902 regs
.x
[rcount
++] = (DWORD_PTR
)instance
; /* the This pointer is always the first parameter */
6904 else func
= (void *)offset
;
6906 /* maximum size for an argument is 16 */
6907 args
= heap_alloc( 16 * count
);
6909 for (i
= 0; i
< count
; i
++)
6911 VARIANT
*arg
= vargs
[i
];
6916 if (fpcount
< 8) regs
.fp
[fpcount
++].f
= V_R4(arg
);
6917 else *(float *)&args
[argspos
++] = V_R4(arg
);
6921 if (fpcount
< 8) regs
.fp
[fpcount
++].d
= V_R8(arg
);
6922 else *(double *)&args
[argspos
++] = V_R8(arg
);
6927 memcpy( ®s
.x
[rcount
], arg
, sizeof(*arg
) );
6932 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6937 if (rcount
< 8) regs
.x
[rcount
++] = (DWORD_PTR
)arg
;
6938 else args
[argspos
++] = (DWORD_PTR
)arg
;
6940 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6941 if (rcount
< 8) regs
.x
[rcount
++] = V_BOOL(arg
);
6942 else args
[argspos
++] = V_BOOL(arg
);
6945 if (rcount
< 8) regs
.x
[rcount
++] = V_UI8(arg
);
6946 else args
[argspos
++] = V_UI8(arg
);
6949 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(types
[i
]), debugstr_variant(arg
));
6952 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 16-byte */
6958 return E_INVALIDARG
;
6961 regs
.x
[8] = (DWORD_PTR
)result
; /* x8 is a pointer to the result */
6962 call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6965 V_R4(result
) = call_float_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6969 V_R8(result
) = call_double_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6972 V_UI8(result
) = call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6976 if (ret_type
!= VT_VARIANT
) V_VT(result
) = ret_type
;
6977 TRACE("retval: %s\n", debugstr_variant(result
));
6981 #else /* __aarch64__ */
6983 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6984 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6986 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6987 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6993 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6996 ITypeInfo
*tinfo2
= NULL
;
6997 TYPEATTR
*tattr
= NULL
;
6999 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
7002 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, hr %#lx.\n", tdesc
->u
.hreftype
, hr
);
7005 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
7008 ERR("ITypeInfo_GetTypeAttr failed, hr %#lx.\n", hr
);
7009 ITypeInfo_Release(tinfo2
);
7013 switch (tattr
->typekind
)
7020 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
7023 case TKIND_INTERFACE
:
7024 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
7030 case TKIND_DISPATCH
:
7039 FIXME("TKIND_RECORD unhandled.\n");
7044 FIXME("TKIND_UNION unhandled.\n");
7049 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
7053 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7054 ITypeInfo_Release(tinfo2
);
7058 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
7062 /* enforce only one level of pointer indirection */
7063 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
7065 tdesc
= tdesc
->u
.lptdesc
;
7067 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7068 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7069 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7070 if ((tdesc
->vt
== VT_USERDEFINED
) ||
7071 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
7073 VARTYPE vt_userdefined
= 0;
7074 const TYPEDESC
*tdesc_userdefined
= tdesc
;
7075 if (tdesc
->vt
== VT_PTR
)
7077 vt_userdefined
= VT_BYREF
;
7078 tdesc_userdefined
= tdesc
->u
.lptdesc
;
7080 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
7082 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
7083 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
7085 *vt
|= vt_userdefined
;
7097 case VT_USERDEFINED
:
7098 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
7105 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
7106 hr
= DISP_E_BADVARTYPE
;
7110 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
7125 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, HREFTYPE href
, GUID
*guid
)
7132 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
7136 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
7138 ITypeInfo_Release(tinfo2
);
7142 switch(tattr
->typekind
) {
7144 hres
= get_iface_guid(tinfo2
, tattr
->tdescAlias
.u
.hreftype
, guid
);
7147 case TKIND_INTERFACE
:
7148 case TKIND_DISPATCH
:
7149 *guid
= tattr
->guid
;
7153 for (i
= 0; i
< tattr
->cImplTypes
; i
++)
7155 ITypeInfo_GetImplTypeFlags(tinfo2
, i
, &flags
);
7156 if (flags
& IMPLTYPEFLAG_FDEFAULT
)
7160 if (i
== tattr
->cImplTypes
)
7163 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo2
, i
, &href
);
7164 if (SUCCEEDED(hres
))
7165 hres
= get_iface_guid(tinfo2
, href
, guid
);
7169 ERR("Unexpected typekind %d\n", tattr
->typekind
);
7170 hres
= E_UNEXPECTED
;
7173 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7174 ITypeInfo_Release(tinfo2
);
7178 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
7180 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
7183 #define INVBUF_ELEMENT_SIZE \
7184 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7185 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7186 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7187 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7188 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7189 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7190 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7191 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7193 static HRESULT WINAPI
ITypeInfo_fnInvoke(
7198 DISPPARAMS
*pDispParams
,
7199 VARIANT
*pVarResult
,
7200 EXCEPINFO
*pExcepInfo
,
7203 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7205 unsigned int var_index
;
7208 const TLBFuncDesc
*pFuncInfo
;
7211 TRACE("%p, %p, %ld, %#x, %p, %p, %p, %p.\n", iface
, pIUnk
, memid
, wFlags
, pDispParams
,
7212 pVarResult
, pExcepInfo
, pArgErr
);
7214 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7215 return DISP_E_MEMBERNOTFOUND
;
7219 ERR("NULL pDispParams not allowed\n");
7220 return E_INVALIDARG
;
7223 dump_DispParms(pDispParams
);
7225 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7227 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7228 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7229 return E_INVALIDARG
;
7232 /* we do this instead of using GetFuncDesc since it will return a fake
7233 * FUNCDESC for dispinterfaces and we want the real function description */
7234 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7235 pFuncInfo
= &This
->funcdescs
[fdc
];
7236 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7237 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7238 !func_restricted( &pFuncInfo
->funcdesc
))
7242 if (fdc
< This
->typeattr
.cFuncs
) {
7243 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7247 TRACE("invoking:\n");
7248 dump_TLBFuncDescOne(pFuncInfo
);
7251 switch (func_desc
->funckind
) {
7252 case FUNC_PUREVIRTUAL
:
7253 case FUNC_VIRTUAL
: {
7254 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7256 VARIANT retval
= {{{0}}}; /* pointer for storing byref retvals in */
7257 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7258 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7259 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7260 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7261 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7262 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7263 UINT vargs_converted
=0;
7268 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7270 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7272 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7273 hres
= DISP_E_PARAMNOTFOUND
;
7278 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7280 ERR("functions with the vararg attribute do not support named arguments\n");
7281 hres
= DISP_E_NONAMEDARGS
;
7285 for (i
= 0; i
< func_desc
->cParams
; i
++)
7287 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7288 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7293 TRACE("changing args\n");
7294 for (i
= 0; i
< func_desc
->cParams
; i
++)
7296 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7297 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7298 VARIANTARG
*src_arg
;
7300 if (wParamFlags
& PARAMFLAG_FLCID
)
7302 prgpvarg
[i
] = &rgvarg
[i
];
7303 V_VT(prgpvarg
[i
]) = VT_I4
;
7304 V_I4(prgpvarg
[i
]) = This
->pTypeLib
->lcid
;
7310 for (j
= 0; j
< cNamedArgs
; j
++)
7312 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7314 src_arg
= &pDispParams
->rgvarg
[j
];
7319 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7321 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7325 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7327 /* under most conditions the caller is not allowed to
7328 * pass in a dispparam arg in the index of what would be
7329 * the retval parameter. however, there is an exception
7330 * where the extra parameter is used in an extra
7331 * IDispatch::Invoke below */
7332 if ((i
< pDispParams
->cArgs
) &&
7333 ((func_desc
->cParams
!= 1) || !pVarResult
||
7334 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7336 hres
= DISP_E_BADPARAMCOUNT
;
7340 /* note: this check is placed so that if the caller passes
7341 * in a VARIANTARG for the retval we just ignore it, like
7343 if (i
== func_desc
->cParams
- 1)
7345 prgpvarg
[i
] = &rgvarg
[i
];
7346 V_BYREF(prgpvarg
[i
]) = &retval
;
7347 V_VT(prgpvarg
[i
]) = rgvt
[i
];
7351 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7352 hres
= E_UNEXPECTED
;
7356 else if (src_arg
&& !((wParamFlags
& PARAMFLAG_FOPT
) &&
7357 V_VT(src_arg
) == VT_ERROR
&& V_ERROR(src_arg
) == DISP_E_PARAMNOTFOUND
))
7359 TRACE("%s\n", debugstr_variant(src_arg
));
7361 if(rgvt
[i
]!=V_VT(src_arg
))
7363 if (rgvt
[i
] == VT_VARIANT
)
7364 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7365 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7367 if (rgvt
[i
] == V_VT(src_arg
))
7368 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7371 if (wParamFlags
& PARAMFLAG_FIN
)
7372 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7373 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7375 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7377 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7379 SAFEARRAYBOUND bound
;
7383 bound
.cElements
= pDispParams
->cArgs
-i
;
7384 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7386 ERR("SafeArrayCreate failed\n");
7389 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7392 ERR("SafeArrayAccessData failed with %#lx.\n", hres
);
7393 SafeArrayDestroy(a
);
7396 for (j
= 0; j
< bound
.cElements
; j
++)
7397 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7398 hres
= SafeArrayUnaccessData(a
);
7401 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres
);
7402 SafeArrayDestroy(a
);
7405 if (rgvt
[i
] & VT_BYREF
)
7406 V_BYREF(&rgvarg
[i
]) = &a
;
7408 V_ARRAY(&rgvarg
[i
]) = a
;
7409 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7411 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7413 if (wParamFlags
& PARAMFLAG_FIN
)
7414 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7416 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7417 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7418 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7420 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7422 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7423 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7427 /* FIXME: this doesn't work for VT_BYREF arguments if
7428 * they are not the same type as in the paramdesc */
7429 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7430 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7431 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7436 ERR("failed to convert param %d to %s from %s\n", i
,
7437 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7440 prgpvarg
[i
] = &rgvarg
[i
];
7444 prgpvarg
[i
] = src_arg
;
7447 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7448 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7449 && V_UNKNOWN(prgpvarg
[i
])) {
7450 IUnknown
*userdefined_iface
;
7453 if (tdesc
->vt
== VT_PTR
)
7454 tdesc
= tdesc
->u
.lptdesc
;
7456 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->u
.hreftype
, &guid
);
7460 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7462 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7466 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7467 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7470 else if (wParamFlags
& PARAMFLAG_FOPT
)
7473 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7474 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7476 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7482 /* if the function wants a pointer to a variant then
7483 * set that up, otherwise just pass the VT_ERROR in
7484 * the argument by value */
7485 if (rgvt
[i
] & VT_BYREF
)
7487 V_VT(&missing_arg
[i
]) = VT_ERROR
;
7488 V_ERROR(&missing_arg
[i
]) = DISP_E_PARAMNOTFOUND
;
7490 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7491 V_VARIANTREF(arg
) = &missing_arg
[i
];
7495 V_VT(arg
) = VT_ERROR
;
7496 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
7502 hres
= DISP_E_BADPARAMCOUNT
;
7506 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7508 /* VT_VOID is a special case for return types, so it is not
7509 * handled in the general function */
7510 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7511 V_VT(&varresult
) = VT_EMPTY
;
7514 V_VT(&varresult
) = 0;
7515 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7516 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7519 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7520 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7521 prgpvarg
, &varresult
);
7523 vargs_converted
= 0;
7525 for (i
= 0; i
< func_desc
->cParams
; i
++)
7527 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7529 if (wParamFlags
& PARAMFLAG_FLCID
)
7531 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7533 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7537 VariantInit(pVarResult
);
7538 /* deref return value */
7539 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7542 VARIANT_ClearInd(prgpvarg
[i
]);
7544 else if (vargs_converted
< pDispParams
->cArgs
)
7546 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7547 if (wParamFlags
& PARAMFLAG_FOUT
)
7549 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7551 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7555 ERR("failed to convert param %d to vt %d\n", i
,
7556 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7561 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7562 func_desc
->cParamsOpt
< 0 &&
7563 i
== func_desc
->cParams
-1)
7565 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7568 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7571 ERR("SafeArrayGetUBound failed with %#lx.\n", hres
);
7574 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7577 ERR("SafeArrayAccessData failed with %#lx.\n", hres
);
7580 for (j
= 0; j
<= ubound
; j
++)
7581 VariantClear(&v
[j
]);
7582 hres
= SafeArrayUnaccessData(a
);
7585 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres
);
7589 VariantClear(&rgvarg
[i
]);
7592 else if (wParamFlags
& PARAMFLAG_FOPT
)
7594 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7595 VariantClear(&rgvarg
[i
]);
7598 VariantClear(&missing_arg
[i
]);
7601 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7603 WARN("invoked function failed with error %#lx.\n", V_ERROR(&varresult
));
7604 hres
= DISP_E_EXCEPTION
;
7607 IErrorInfo
*pErrorInfo
;
7608 pExcepInfo
->scode
= V_ERROR(&varresult
);
7609 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7611 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7612 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7613 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7614 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7616 IErrorInfo_Release(pErrorInfo
);
7620 if (V_VT(&varresult
) != VT_ERROR
)
7622 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7626 VariantClear(pVarResult
);
7627 *pVarResult
= varresult
;
7630 VariantClear(&varresult
);
7633 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7634 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7635 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7636 (pDispParams
->cArgs
!= 0))
7638 if (V_VT(pVarResult
) == VT_DISPATCH
)
7640 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7641 /* Note: not VariantClear; we still need the dispatch
7642 * pointer to be valid */
7643 VariantInit(pVarResult
);
7644 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7645 GetSystemDefaultLCID(), wFlags
,
7646 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7647 IDispatch_Release(pDispatch
);
7651 VariantClear(pVarResult
);
7652 hres
= DISP_E_NOTACOLLECTION
;
7660 case FUNC_DISPATCH
: {
7663 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7664 if (SUCCEEDED(hres
)) {
7665 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7666 hres
= IDispatch_Invoke(
7667 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7668 pVarResult
,pExcepInfo
,pArgErr
7671 FIXME("IDispatch::Invoke failed with %#lx. (Could be not a real error?)\n", hres
);
7672 IDispatch_Release(disp
);
7674 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7678 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7683 TRACE("-- %#lx\n", hres
);
7686 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7689 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7690 if(FAILED(hres
)) return hres
;
7692 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7693 dump_VARDESC(var_desc
);
7694 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7698 /* not found, look for it in inherited interfaces */
7699 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7700 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7701 if(This
->impltypes
) {
7702 /* recursive search */
7704 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7705 if(SUCCEEDED(hres
)){
7706 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7707 ITypeInfo_Release(pTInfo
);
7710 WARN("Could not search inherited interface!\n");
7713 WARN("did not find member id %ld, flags 0x%x!\n", memid
, wFlags
);
7714 return DISP_E_MEMBERNOTFOUND
;
7717 /* ITypeInfo::GetDocumentation
7719 * Retrieves the documentation string, the complete Help file name and path,
7720 * and the context ID for the Help topic for a specified type description.
7722 * (Can be tested by the Visual Basic Editor in Word for instance.)
7724 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7725 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7726 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7728 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7729 const TLBFuncDesc
*pFDesc
;
7730 const TLBVarDesc
*pVDesc
;
7731 TRACE("%p, %ld, %p, %p, %p, %p.\n",
7732 iface
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7733 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7735 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7737 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7739 *pdwHelpContext
=This
->dwHelpContext
;
7741 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7743 }else {/* for a member */
7744 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
7747 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7749 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7751 *pdwHelpContext
=pFDesc
->helpcontext
;
7753 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7756 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
7759 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7761 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7763 *pdwHelpContext
=pVDesc
->HelpContext
;
7765 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7770 if(This
->impltypes
&&
7771 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7772 /* recursive search */
7775 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7776 if(SUCCEEDED(result
)) {
7777 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7778 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7779 ITypeInfo_Release(pTInfo
);
7782 WARN("Could not search inherited interface!\n");
7785 WARN("member %ld not found\n", memid
);
7786 return TYPE_E_ELEMENTNOTFOUND
;
7789 /* ITypeInfo::GetDllEntry
7791 * Retrieves a description or specification of an entry point for a function
7794 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7795 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7798 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7799 const TLBFuncDesc
*pFDesc
;
7801 TRACE("%p, %#lx, %d, %p, %p, %p.\n", iface
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7803 if (pBstrDllName
) *pBstrDllName
= NULL
;
7804 if (pBstrName
) *pBstrName
= NULL
;
7805 if (pwOrdinal
) *pwOrdinal
= 0;
7807 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7808 return TYPE_E_BADMODULEKIND
;
7810 pFDesc
= TLB_get_funcdesc_by_memberid_invkind(This
, memid
, invKind
);
7811 if (!pFDesc
) return TYPE_E_ELEMENTNOTFOUND
;
7813 dump_TypeInfo(This
);
7814 if (TRACE_ON(ole
)) dump_TLBFuncDescOne(pFDesc
);
7816 if (pBstrDllName
) *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7818 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1))
7820 if (pBstrName
) *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7821 if (pwOrdinal
) *pwOrdinal
= -1;
7825 if (pBstrName
) *pBstrName
= NULL
;
7826 if (pwOrdinal
) *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7831 /* internal function to make the inherited interfaces' methods appear
7832 * part of the interface */
7833 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7834 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7836 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7839 TRACE("%p, %#lx.\n", iface
, *hRefType
);
7841 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7843 ITypeInfo
*pSubTypeInfo
;
7845 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7849 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7851 ITypeInfo_Release(pSubTypeInfo
);
7855 *hRefType
-= DISPATCH_HREF_OFFSET
;
7857 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7858 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7863 /* ITypeInfo::GetRefTypeInfo
7865 * If a type description references other type descriptions, it retrieves
7866 * the referenced type descriptions.
7868 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7871 ITypeInfo
**ppTInfo
)
7873 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7874 ITypeInfo
*type_info
= NULL
;
7875 HRESULT result
= E_FAIL
;
7876 TLBRefType
*ref_type
;
7880 return E_INVALIDARG
;
7882 if ((INT
)hRefType
< 0) {
7883 ITypeInfoImpl
*pTypeInfoImpl
;
7885 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7886 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7887 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7888 return TYPE_E_ELEMENTNOTFOUND
;
7890 /* when we meet a DUAL typeinfo, we must create the alternate
7893 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7895 *pTypeInfoImpl
= *This
;
7896 pTypeInfoImpl
->ref
= 0;
7897 list_init(&pTypeInfoImpl
->custdata_list
);
7899 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7900 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7902 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7904 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7905 /* the AddRef implicitly adds a reference to the parent typelib, which
7906 * stops the copied data from being destroyed until the new typeinfo's
7907 * refcount goes to zero, but we need to signal to the new instance to
7908 * not free its data structures when it is destroyed */
7909 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7910 ITypeInfo_AddRef(*ppTInfo
);
7912 TRACE("got dual interface %p\n", *ppTInfo
);
7916 if ((hRefType
& DISPATCH_HREF_MASK
) && (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7917 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &hRefType
, ppTInfo
);
7919 if(!(hRefType
& 0x1))
7921 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7923 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7926 type_info
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7927 ITypeInfo_AddRef(type_info
);
7935 ITypeLib
*pTLib
= NULL
;
7937 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7939 if(ref_type
->reference
== (hRefType
& (~0x3)))
7942 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7944 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
7948 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7950 TRACE("internal reference\n");
7951 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7953 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7954 TRACE("typeinfo in imported typelib that is already loaded\n");
7955 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7956 ITypeLib_AddRef(pTLib
);
7959 /* Search in cached typelibs */
7960 ITypeLibImpl
*entry
;
7962 EnterCriticalSection(&cache_section
);
7963 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
7966 && IsEqualIID(&entry
->guid
->guid
, TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
))
7967 && entry
->ver_major
== ref_type
->pImpTLInfo
->wVersionMajor
7968 && entry
->ver_minor
== ref_type
->pImpTLInfo
->wVersionMinor
7969 && entry
->set_lcid
== ref_type
->pImpTLInfo
->lcid
)
7971 TRACE("got cached %p\n", entry
);
7972 pTLib
= (ITypeLib
*)&entry
->ITypeLib2_iface
;
7973 ITypeLib_AddRef(pTLib
);
7978 LeaveCriticalSection(&cache_section
);
7984 /* Search on disk */
7985 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7986 ref_type
->pImpTLInfo
->wVersionMajor
,
7987 ref_type
->pImpTLInfo
->wVersionMinor
,
7988 This
->pTypeLib
->syskind
,
7989 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7991 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7993 result
= LoadTypeLib(libnam
, &pTLib
);
7994 SysFreeString(libnam
);
7997 if(SUCCEEDED(result
)) {
7998 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7999 ITypeLib_AddRef(pTLib
);
8003 if(SUCCEEDED(result
)) {
8004 if(ref_type
->index
== TLB_REF_USE_GUID
)
8005 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), &type_info
);
8007 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, &type_info
);
8010 ITypeLib_Release(pTLib
);
8013 WARN("(%p) failed hreftype %#lx.\n", iface
, hRefType
);
8018 if ((hRefType
& 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info
, -2, ppTInfo
)))
8019 ITypeInfo_Release(type_info
);
8020 else *ppTInfo
= type_info
;
8022 TRACE("%p, hreftype %#lx, loaded %s (%p)\n", iface
, hRefType
,
8023 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
8027 /* ITypeInfo::AddressOfMember
8029 * Retrieves the addresses of static functions or variables, such as those
8032 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
8033 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
8040 TRACE("%p, %lx, %#x, %p.\n", iface
, memid
, invKind
, ppv
);
8042 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
8046 module
= LoadLibraryW(dll
);
8049 ERR("couldn't load %s\n", debugstr_w(dll
));
8051 SysFreeString(entry
);
8052 return STG_E_FILENOTFOUND
;
8054 /* FIXME: store library somewhere where we can free it */
8059 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
8060 entryA
= heap_alloc(len
);
8061 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
8063 *ppv
= GetProcAddress(module
, entryA
);
8065 ERR("function not found %s\n", debugstr_a(entryA
));
8071 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
8073 ERR("function not found %d\n", ordinal
);
8077 SysFreeString(entry
);
8080 return TYPE_E_DLLFUNCTIONNOTFOUND
;
8085 /* ITypeInfo::CreateInstance
8087 * Creates a new instance of a type that describes a component object class
8090 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
8091 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
8093 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8097 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
8103 WARN("Not able to aggregate\n");
8104 return CLASS_E_NOAGGREGATION
;
8107 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
8108 if(FAILED(hr
)) return hr
;
8110 if(pTA
->typekind
!= TKIND_COCLASS
)
8112 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
8118 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
8121 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
8122 TRACE("GetActiveObject rets %#lx.\n", hr
);
8125 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
8126 IUnknown_Release(pUnk
);
8131 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
8132 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8136 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8140 /* ITypeInfo::GetMops
8142 * Retrieves marshalling information.
8144 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
, BSTR
*pBstrMops
)
8146 FIXME("%p, %ld stub!\n", iface
, memid
);
8151 /* ITypeInfo::GetContainingTypeLib
8153 * Retrieves the containing type library and the index of the type description
8154 * within that type library.
8156 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8157 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8159 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8161 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8163 *pIndex
=This
->index
;
8164 TRACE("returning pIndex=%d\n", *pIndex
);
8168 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8169 ITypeLib_AddRef(*ppTLib
);
8170 TRACE("returning ppTLib=%p\n", *ppTLib
);
8176 /* ITypeInfo::ReleaseTypeAttr
8178 * Releases a TYPEATTR previously returned by Get
8181 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8182 TYPEATTR
* pTypeAttr
)
8184 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8185 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8186 heap_free(pTypeAttr
);
8189 /* ITypeInfo::ReleaseFuncDesc
8191 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8193 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8195 FUNCDESC
*pFuncDesc
)
8197 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8200 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8202 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8203 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8204 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8206 SysFreeString((BSTR
)pFuncDesc
);
8209 /* ITypeInfo::ReleaseVarDesc
8211 * Releases a VARDESC previously returned by GetVarDesc.
8213 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8216 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8217 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8219 TLB_FreeVarDesc(pVarDesc
);
8222 /* ITypeInfo2::GetTypeKind
8224 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8227 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8228 TYPEKIND
*pTypeKind
)
8230 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8231 *pTypeKind
= This
->typeattr
.typekind
;
8232 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8236 /* ITypeInfo2::GetTypeFlags
8238 * Returns the type flags without any allocations. This returns a DWORD type
8239 * flag, which expands the type flags without growing the TYPEATTR (type
8243 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8245 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8246 TRACE("%p, %p.\n", iface
, pTypeFlags
);
8247 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8251 /* ITypeInfo2::GetFuncIndexOfMemId
8252 * Binds to a specific member based on a known DISPID, where the member name
8253 * is not known (for example, when binding to a default member).
8256 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8257 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8259 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8263 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8264 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8265 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8268 if(fdc
< This
->typeattr
.cFuncs
) {
8272 result
= TYPE_E_ELEMENTNOTFOUND
;
8274 TRACE("%p, %#lx, %#x, hr %#lx.\n", iface
, memid
, invKind
, result
);
8278 /* TypeInfo2::GetVarIndexOfMemId
8280 * Binds to a specific member based on a known DISPID, where the member name
8281 * is not known (for example, when binding to a default member).
8284 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8285 MEMBERID memid
, UINT
*pVarIndex
)
8287 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8288 TLBVarDesc
*pVarInfo
;
8290 TRACE("%p, %ld, %p.\n", iface
, memid
, pVarIndex
);
8292 pVarInfo
= TLB_get_vardesc_by_memberid(This
, memid
);
8294 return TYPE_E_ELEMENTNOTFOUND
;
8296 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8301 /* ITypeInfo2::GetCustData
8303 * Gets the custom data
8305 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8310 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8311 TLBCustData
*pCData
;
8313 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8315 if(!guid
|| !pVarVal
)
8316 return E_INVALIDARG
;
8318 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8320 VariantInit( pVarVal
);
8322 VariantCopy( pVarVal
, &pCData
->data
);
8324 VariantClear( pVarVal
);
8328 /* ITypeInfo2::GetFuncCustData
8330 * Gets the custom data
8332 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8338 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8339 const TLBFuncDesc
*desc
;
8344 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8346 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &desc
, &hrefoffset
);
8349 WARN("description for function %d not found\n", index
);
8353 VariantInit(pVarVal
);
8354 data
= TLB_get_custdata_by_guid(&desc
->custdata_list
, guid
);
8355 return data
? VariantCopy(pVarVal
, &data
->data
) : S_OK
;
8358 /* ITypeInfo2::GetParamCustData
8360 * Gets the custom data
8362 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8369 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8370 const TLBFuncDesc
*pFDesc
;
8371 TLBCustData
*pCData
;
8375 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8376 debugstr_guid(guid
), pVarVal
);
8378 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8382 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8383 return TYPE_E_ELEMENTNOTFOUND
;
8385 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8387 return TYPE_E_ELEMENTNOTFOUND
;
8389 VariantInit(pVarVal
);
8390 VariantCopy(pVarVal
, &pCData
->data
);
8395 /* ITypeInfo2::GetVarCustData
8397 * Gets the custom data
8399 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8405 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8406 TLBCustData
*pCData
;
8407 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8409 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8411 if(index
>= This
->typeattr
.cVars
)
8412 return TYPE_E_ELEMENTNOTFOUND
;
8414 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8416 return TYPE_E_ELEMENTNOTFOUND
;
8418 VariantInit(pVarVal
);
8419 VariantCopy(pVarVal
, &pCData
->data
);
8424 /* ITypeInfo2::GetImplCustData
8426 * Gets the custom data
8428 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8434 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8435 TLBCustData
*pCData
;
8436 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8438 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8440 if(index
>= This
->typeattr
.cImplTypes
)
8441 return TYPE_E_ELEMENTNOTFOUND
;
8443 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8445 return TYPE_E_ELEMENTNOTFOUND
;
8447 VariantInit(pVarVal
);
8448 VariantCopy(pVarVal
, &pCData
->data
);
8453 /* ITypeInfo2::GetDocumentation2
8455 * Retrieves the documentation string, the complete Help file name and path,
8456 * the localization context to use, and the context ID for the library Help
8457 * topic in the Help file.
8460 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8464 BSTR
*pbstrHelpString
,
8465 DWORD
*pdwHelpStringContext
,
8466 BSTR
*pbstrHelpStringDll
)
8468 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8469 const TLBFuncDesc
*pFDesc
;
8470 const TLBVarDesc
*pVDesc
;
8471 TRACE("%p, %ld, %#lx, %p, %p, %p.\n",
8472 iface
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8473 pbstrHelpStringDll
);
8474 /* the help string should be obtained from the helpstringdll,
8475 * using the _DLLGetDocumentation function, based on the supplied
8476 * lcid. Nice to do sometime...
8478 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8480 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8481 if(pdwHelpStringContext
)
8482 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8483 if(pbstrHelpStringDll
)
8484 *pbstrHelpStringDll
=
8485 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8487 }else {/* for a member */
8488 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
8491 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8492 if(pdwHelpStringContext
)
8493 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8494 if(pbstrHelpStringDll
)
8495 *pbstrHelpStringDll
=
8496 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8499 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
8502 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8503 if(pdwHelpStringContext
)
8504 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8505 if(pbstrHelpStringDll
)
8506 *pbstrHelpStringDll
=
8507 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8511 return TYPE_E_ELEMENTNOTFOUND
;
8514 /* ITypeInfo2::GetAllCustData
8516 * Gets all custom data items for the Type info.
8519 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8521 CUSTDATA
*pCustData
)
8523 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8525 TRACE("%p %p\n", This
, pCustData
);
8527 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8530 /* ITypeInfo2::GetAllFuncCustData
8532 * Gets all custom data items for the specified Function
8535 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8538 CUSTDATA
*pCustData
)
8540 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8541 const TLBFuncDesc
*pFDesc
;
8545 TRACE("%p %u %p\n", This
, index
, pCustData
);
8547 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &pFDesc
, &hrefoffset
);
8551 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8554 /* ITypeInfo2::GetAllParamCustData
8556 * Gets all custom data items for the Functions
8559 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8560 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8562 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8563 const TLBFuncDesc
*pFDesc
;
8567 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8569 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8573 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8574 return TYPE_E_ELEMENTNOTFOUND
;
8576 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8579 /* ITypeInfo2::GetAllVarCustData
8581 * Gets all custom data items for the specified Variable
8584 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8585 UINT index
, CUSTDATA
*pCustData
)
8587 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8588 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8590 TRACE("%p %u %p\n", This
, index
, pCustData
);
8592 if(index
>= This
->typeattr
.cVars
)
8593 return TYPE_E_ELEMENTNOTFOUND
;
8595 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8598 /* ITypeInfo2::GetAllImplCustData
8600 * Gets all custom data items for the specified implementation type
8603 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8606 CUSTDATA
*pCustData
)
8608 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8609 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8611 TRACE("%p %u %p\n", This
, index
, pCustData
);
8613 if(index
>= This
->typeattr
.cImplTypes
)
8614 return TYPE_E_ELEMENTNOTFOUND
;
8616 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8619 static const ITypeInfo2Vtbl tinfvt
=
8622 ITypeInfo_fnQueryInterface
,
8624 ITypeInfo_fnRelease
,
8626 ITypeInfo_fnGetTypeAttr
,
8627 ITypeInfo_fnGetTypeComp
,
8628 ITypeInfo_fnGetFuncDesc
,
8629 ITypeInfo_fnGetVarDesc
,
8630 ITypeInfo_fnGetNames
,
8631 ITypeInfo_fnGetRefTypeOfImplType
,
8632 ITypeInfo_fnGetImplTypeFlags
,
8633 ITypeInfo_fnGetIDsOfNames
,
8635 ITypeInfo_fnGetDocumentation
,
8636 ITypeInfo_fnGetDllEntry
,
8637 ITypeInfo_fnGetRefTypeInfo
,
8638 ITypeInfo_fnAddressOfMember
,
8639 ITypeInfo_fnCreateInstance
,
8640 ITypeInfo_fnGetMops
,
8641 ITypeInfo_fnGetContainingTypeLib
,
8642 ITypeInfo_fnReleaseTypeAttr
,
8643 ITypeInfo_fnReleaseFuncDesc
,
8644 ITypeInfo_fnReleaseVarDesc
,
8646 ITypeInfo2_fnGetTypeKind
,
8647 ITypeInfo2_fnGetTypeFlags
,
8648 ITypeInfo2_fnGetFuncIndexOfMemId
,
8649 ITypeInfo2_fnGetVarIndexOfMemId
,
8650 ITypeInfo2_fnGetCustData
,
8651 ITypeInfo2_fnGetFuncCustData
,
8652 ITypeInfo2_fnGetParamCustData
,
8653 ITypeInfo2_fnGetVarCustData
,
8654 ITypeInfo2_fnGetImplTypeCustData
,
8655 ITypeInfo2_fnGetDocumentation2
,
8656 ITypeInfo2_fnGetAllCustData
,
8657 ITypeInfo2_fnGetAllFuncCustData
,
8658 ITypeInfo2_fnGetAllParamCustData
,
8659 ITypeInfo2_fnGetAllVarCustData
,
8660 ITypeInfo2_fnGetAllImplTypeCustData
,
8663 /******************************************************************************
8664 * CreateDispTypeInfo [OLEAUT32.31]
8666 * Build type information for an object so it can be called through an
8667 * IDispatch interface.
8670 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8671 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8674 * This call allows an objects methods to be accessed through IDispatch, by
8675 * building an ITypeInfo object that IDispatch can use to call through.
8677 HRESULT WINAPI
CreateDispTypeInfo(
8678 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8679 LCID lcid
, /* [I] Locale Id */
8680 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8682 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8683 ITypeLibImpl
*pTypeLibImpl
;
8684 unsigned int param
, func
;
8685 TLBFuncDesc
*pFuncDesc
;
8689 pTypeLibImpl
= TypeLibImpl_Constructor();
8690 if (!pTypeLibImpl
) return E_FAIL
;
8692 pTypeLibImpl
->TypeInfoCount
= 2;
8693 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8695 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8696 pTIIface
->pTypeLib
= pTypeLibImpl
;
8697 pTIIface
->index
= 0;
8698 pTIIface
->Name
= NULL
;
8699 pTIIface
->dwHelpContext
= -1;
8700 pTIIface
->guid
= NULL
;
8701 pTIIface
->typeattr
.lcid
= lcid
;
8702 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8703 pTIIface
->typeattr
.wMajorVerNum
= 0;
8704 pTIIface
->typeattr
.wMinorVerNum
= 0;
8705 pTIIface
->typeattr
.cbAlignment
= 2;
8706 pTIIface
->typeattr
.cbSizeInstance
= -1;
8707 pTIIface
->typeattr
.cbSizeVft
= -1;
8708 pTIIface
->typeattr
.cFuncs
= 0;
8709 pTIIface
->typeattr
.cImplTypes
= 0;
8710 pTIIface
->typeattr
.cVars
= 0;
8711 pTIIface
->typeattr
.wTypeFlags
= 0;
8712 pTIIface
->hreftype
= 0;
8714 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8715 pFuncDesc
= pTIIface
->funcdescs
;
8716 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8717 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8718 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8719 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8720 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8721 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8722 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8723 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8724 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8725 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8726 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8727 pFuncDesc
->funcdesc
.cScodes
= 0;
8728 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8729 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8730 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8731 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8732 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8733 md
->cArgs
* sizeof(ELEMDESC
));
8734 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8735 for(param
= 0; param
< md
->cArgs
; param
++) {
8736 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8737 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8739 pFuncDesc
->helpcontext
= 0;
8740 pFuncDesc
->HelpStringContext
= 0;
8741 pFuncDesc
->HelpString
= NULL
;
8742 pFuncDesc
->Entry
= NULL
;
8743 list_init(&pFuncDesc
->custdata_list
);
8744 pTIIface
->typeattr
.cFuncs
++;
8748 dump_TypeInfo(pTIIface
);
8750 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8751 pTIClass
->pTypeLib
= pTypeLibImpl
;
8752 pTIClass
->index
= 1;
8753 pTIClass
->Name
= NULL
;
8754 pTIClass
->dwHelpContext
= -1;
8755 pTIClass
->guid
= NULL
;
8756 pTIClass
->typeattr
.lcid
= lcid
;
8757 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8758 pTIClass
->typeattr
.wMajorVerNum
= 0;
8759 pTIClass
->typeattr
.wMinorVerNum
= 0;
8760 pTIClass
->typeattr
.cbAlignment
= 2;
8761 pTIClass
->typeattr
.cbSizeInstance
= -1;
8762 pTIClass
->typeattr
.cbSizeVft
= -1;
8763 pTIClass
->typeattr
.cFuncs
= 0;
8764 pTIClass
->typeattr
.cImplTypes
= 1;
8765 pTIClass
->typeattr
.cVars
= 0;
8766 pTIClass
->typeattr
.wTypeFlags
= 0;
8767 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8769 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8771 ref
= heap_alloc_zero(sizeof(*ref
));
8772 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8773 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8775 dump_TypeInfo(pTIClass
);
8777 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8779 ITypeInfo_AddRef(*pptinfo
);
8780 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8786 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8788 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8790 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8793 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8795 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8797 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8800 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8802 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8804 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8807 static HRESULT WINAPI
ITypeComp_fnBind(
8812 ITypeInfo
** ppTInfo
,
8813 DESCKIND
* pDescKind
,
8816 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8817 const TLBFuncDesc
*pFDesc
;
8818 const TLBVarDesc
*pVDesc
;
8819 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8822 TRACE("%p, %s, %#lx, 0x%x, %p, %p, %p.\n", iface
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8824 *pDescKind
= DESCKIND_NONE
;
8825 pBindPtr
->lpfuncdesc
= NULL
;
8828 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8829 pFDesc
= &This
->funcdescs
[fdc
];
8830 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8831 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8834 /* name found, but wrong flags */
8835 hr
= TYPE_E_TYPEMISMATCH
;
8839 if (fdc
< This
->typeattr
.cFuncs
)
8841 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8843 &pBindPtr
->lpfuncdesc
,
8844 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8847 *pDescKind
= DESCKIND_FUNCDESC
;
8848 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8849 ITypeInfo_AddRef(*ppTInfo
);
8852 pVDesc
= TLB_get_vardesc_by_name(This
, szName
);
8854 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8857 *pDescKind
= DESCKIND_VARDESC
;
8858 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8859 ITypeInfo_AddRef(*ppTInfo
);
8864 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8865 /* recursive search */
8869 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8872 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8873 ITypeInfo_Release(pTInfo
);
8877 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8878 ITypeComp_Release(pTComp
);
8879 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8880 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8882 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8883 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8884 SysFreeString((BSTR
)tmp
);
8888 WARN("Could not search inherited interface!\n");
8890 if (hr
== DISP_E_MEMBERNOTFOUND
)
8892 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8896 static HRESULT WINAPI
ITypeComp_fnBindType(
8900 ITypeInfo
** ppTInfo
,
8901 ITypeComp
** ppTComp
)
8903 TRACE("%s, %#lx, %p, %p.\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8905 /* strange behaviour (does nothing) but like the
8908 if (!ppTInfo
|| !ppTComp
)
8917 static const ITypeCompVtbl tcompvt
=
8920 ITypeComp_fnQueryInterface
,
8922 ITypeComp_fnRelease
,
8925 ITypeComp_fnBindType
8928 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8929 ICreateTypeLib2
** ppctlib
)
8934 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8936 if (!szFile
) return E_INVALIDARG
;
8938 This
= TypeLibImpl_Constructor();
8940 return E_OUTOFMEMORY
;
8942 This
->lcid
= GetSystemDefaultLCID();
8943 This
->syskind
= syskind
;
8944 This
->ptr_size
= get_ptr_size(syskind
);
8946 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8948 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8949 return E_OUTOFMEMORY
;
8951 lstrcpyW(This
->path
, szFile
);
8953 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8954 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8958 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8959 REFIID riid
, void **object
)
8961 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8963 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8966 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8968 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8970 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8973 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8975 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8977 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8980 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8981 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8983 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8984 ITypeInfoImpl
*info
;
8987 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8989 if (!ctinfo
|| !name
)
8990 return E_INVALIDARG
;
8992 info
= TLB_get_typeinfo_by_name(This
, name
);
8994 return TYPE_E_NAMECONFLICT
;
8996 if (This
->typeinfos
)
8997 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8998 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
9000 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
9002 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
9004 info
->pTypeLib
= This
;
9005 info
->Name
= TLB_append_str(&This
->name_list
, name
);
9006 info
->index
= This
->TypeInfoCount
;
9007 info
->typeattr
.typekind
= kind
;
9008 info
->typeattr
.cbAlignment
= 4;
9010 switch (info
->typeattr
.typekind
) {
9012 case TKIND_INTERFACE
:
9013 case TKIND_DISPATCH
:
9015 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
9019 info
->typeattr
.cbSizeInstance
= 0;
9022 info
->typeattr
.cbSizeInstance
= 2;
9025 info
->typeattr
.cbSizeInstance
= -0x75;
9028 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
9029 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
9033 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
9034 &IID_ICreateTypeInfo
, (void **)ctinfo
);
9036 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
9040 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
9042 ++This
->TypeInfoCount
;
9047 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
9050 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9052 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
9055 return E_INVALIDARG
;
9057 This
->Name
= TLB_append_str(&This
->name_list
, name
);
9062 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
9063 WORD majorVerNum
, WORD minorVerNum
)
9065 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9067 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
9069 This
->ver_major
= majorVerNum
;
9070 This
->ver_minor
= minorVerNum
;
9075 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
9078 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9080 TRACE("%p %s\n", This
, debugstr_guid(guid
));
9082 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
9087 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
9090 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9092 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
9095 return E_INVALIDARG
;
9097 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
9102 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
9103 LPOLESTR helpFileName
)
9105 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9107 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
9110 return E_INVALIDARG
;
9112 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
9117 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
9120 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9122 TRACE("%p, %ld.\n", iface
, helpContext
);
9124 This
->dwHelpContext
= helpContext
;
9129 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
9132 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9134 TRACE("%p, %#lx.\n", iface
, lcid
);
9136 This
->set_lcid
= lcid
;
9141 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9144 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9146 TRACE("%p %x\n", This
, libFlags
);
9148 This
->libflags
= libFlags
;
9153 typedef struct tagWMSFT_SegContents
{
9156 } WMSFT_SegContents
;
9158 typedef struct tagWMSFT_TLBFile
{
9160 WMSFT_SegContents typeinfo_seg
;
9161 WMSFT_SegContents impfile_seg
;
9162 WMSFT_SegContents impinfo_seg
;
9163 WMSFT_SegContents ref_seg
;
9164 WMSFT_SegContents guidhash_seg
;
9165 WMSFT_SegContents guid_seg
;
9166 WMSFT_SegContents namehash_seg
;
9167 WMSFT_SegContents name_seg
;
9168 WMSFT_SegContents string_seg
;
9169 WMSFT_SegContents typdesc_seg
;
9170 WMSFT_SegContents arraydesc_seg
;
9171 WMSFT_SegContents custdata_seg
;
9172 WMSFT_SegContents cdguids_seg
;
9174 WMSFT_SegContents aux_seg
;
9177 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9178 WMSFT_TLBFile
*file
)
9184 file
->string_seg
.len
= 0;
9185 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9188 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9190 return E_UNEXPECTED
;
9192 size
+= sizeof(INT16
);
9194 size
= (size
+ 4) & ~0x3;
9198 file
->string_seg
.len
+= size
;
9200 /* temporarily use str->offset to store the length of the aligned,
9201 * converted string */
9205 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
9208 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9211 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9212 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9214 heap_free(file
->string_seg
.data
);
9215 return E_UNEXPECTED
;
9218 *((INT16
*)data
) = size
;
9220 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9224 str
->offset
= last_offs
;
9231 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9232 WMSFT_TLBFile
*file
)
9237 MSFT_NameIntro
*last_intro
= NULL
;
9239 file
->header
.nametablecount
= 0;
9240 file
->header
.nametablechars
= 0;
9242 file
->name_seg
.len
= 0;
9243 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9246 size
= lstrlenW(str
->str
);
9247 file
->header
.nametablechars
+= size
;
9248 file
->header
.nametablecount
++;
9250 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9252 return E_UNEXPECTED
;
9254 size
+= sizeof(MSFT_NameIntro
);
9256 size
= (size
+ 4) & ~0x3;
9260 file
->name_seg
.len
+= size
;
9262 /* temporarily use str->offset to store the length of the aligned,
9263 * converted string */
9267 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9268 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
9271 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9273 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9275 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9276 data
+ sizeof(MSFT_NameIntro
),
9277 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9279 heap_free(file
->name_seg
.data
);
9280 return E_UNEXPECTED
;
9282 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9284 intro
->hreftype
= -1; /* TODO? */
9285 intro
->namelen
= size
& 0xFF;
9286 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9287 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9288 intro
->namelen
|= hash
<< 16;
9289 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9290 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9292 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9293 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9295 /* update str->offset to actual value to use in other
9296 * compilation functions that require positions within
9297 * the string table */
9301 str
->offset
= last_offs
;
9306 last_intro
->hreftype
= 0; /* last one is 0? */
9311 static inline int hash_guid(GUID
*guid
)
9315 for (i
= 0; i
< 8; i
++)
9316 hash
^= ((const short *)guid
)[i
];
9321 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9324 MSFT_GuidEntry
*entry
;
9326 int hash_key
, *guidhashtab
;
9328 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9329 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9331 entry
= file
->guid_seg
.data
;
9333 guidhashtab
= file
->guidhash_seg
.data
;
9334 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9335 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9336 entry
->hreftype
= guid
->hreftype
;
9338 hash_key
= hash_guid(&guid
->guid
);
9339 entry
->next_hash
= guidhashtab
[hash_key
];
9340 guidhashtab
[hash_key
] = offs
;
9342 guid
->offset
= offs
;
9343 offs
+= sizeof(MSFT_GuidEntry
);
9350 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9353 VARTYPE arg_type
= V_VT(value
);
9356 DWORD ret
= file
->custdata_seg
.len
;
9358 if(arg_type
== VT_INT
)
9360 if(arg_type
== VT_UINT
)
9364 if(V_VT(value
) != arg_type
) {
9365 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9367 ERR("VariantChangeType failed: %#lx.\n", hres
);
9372 /* Check if default value can be stored in-place */
9377 if(V_UI4(&v
) > 0x3ffffff)
9390 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9393 /* have to allocate space in custdata_seg */
9402 /* Construct the data to be allocated */
9405 if(file
->custdata_seg
.data
){
9406 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9407 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9408 file
->custdata_seg
.len
+= sizeof(int) * 2;
9410 file
->custdata_seg
.len
= sizeof(int) * 2;
9411 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9414 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9415 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9417 /* TODO: Check if the encoded data is already present in custdata_seg */
9423 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9426 if(file
->custdata_seg
.data
){
9427 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9428 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9429 file
->custdata_seg
.len
+= len
;
9431 file
->custdata_seg
.len
= len
;
9432 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9435 *((unsigned short *)data
) = V_VT(value
);
9436 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9437 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9438 if(V_BSTR(&v
)[i
] <= 0x7f)
9439 data
[i
+6] = V_BSTR(&v
)[i
];
9443 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9444 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9447 /* TODO: Check if the encoded data is already present in custdata_seg */
9452 FIXME("Argument type not yet handled\n");
9457 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9459 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9461 DWORD offs
= file
->arraydesc_seg
.len
;
9465 /* TODO: we should check for duplicates, but that's harder because each
9466 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9467 * at the library-level) */
9469 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9470 if(!file
->arraydesc_seg
.data
)
9471 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9473 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9474 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9476 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9477 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9478 for(i
= 0; i
< desc
->cDims
; ++i
){
9479 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9480 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9486 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9492 VARTYPE vt
, subtype
;
9503 vt
= desc
->vt
& VT_TYPEMASK
;
9505 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9507 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9508 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9510 *out_size
+= 2 * sizeof(DWORD
);
9511 }else if(vt
== VT_CARRAY
){
9512 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9513 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9515 }else if(vt
== VT_USERDEFINED
){
9516 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9517 encoded
[1] = desc
->u
.hreftype
;
9518 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9520 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9538 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9541 data
= file
->typdesc_seg
.data
;
9542 while(offs
< file
->typdesc_seg
.len
){
9543 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9545 offs
+= sizeof(encoded
);
9548 file
->typdesc_seg
.len
+= sizeof(encoded
);
9549 if(!file
->typdesc_seg
.data
)
9550 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9552 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9554 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9559 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9561 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9562 DWORD ret
= cdguids_seg
->len
, offs
;
9563 MSFT_CDGuid
*cdguid
;
9566 if(list_empty(custdata_list
))
9569 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9570 if(!cdguids_seg
->data
){
9571 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9573 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9574 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9577 offs
= ret
+ sizeof(MSFT_CDGuid
);
9578 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9579 cdguid
->GuidOffset
= cd
->guid
->offset
;
9580 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9581 cdguid
->next
= offs
;
9582 offs
+= sizeof(MSFT_CDGuid
);
9592 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9593 WMSFT_TLBFile
*file
)
9595 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9596 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9597 MSFT_VarRecord
*varrecord
;
9598 MSFT_FuncRecord
*funcrecord
;
9600 DWORD
*name
, *offsets
, offs
;
9602 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9603 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9605 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9607 /* optional fields */
9608 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9609 if(!list_empty(&desc
->custdata_list
))
9610 recorded_size
+= 7 * sizeof(INT
);
9611 else if(desc
->HelpStringContext
!= 0)
9612 recorded_size
+= 6 * sizeof(INT
);
9614 else if(desc
->Entry
)
9615 recorded_size
+= 3 * sizeof(INT
);
9616 else if(desc
->HelpString
)
9617 recorded_size
+= 2 * sizeof(INT
);
9618 else if(desc
->helpcontext
)
9619 recorded_size
+= sizeof(INT
);
9621 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9623 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9624 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9625 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9630 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9633 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9634 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9636 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9638 /* optional fields */
9639 if(desc
->HelpStringContext
!= 0)
9640 recorded_size
+= 5 * sizeof(INT
);
9641 else if(!list_empty(&desc
->custdata_list
))
9642 recorded_size
+= 4 * sizeof(INT
);
9644 else if(desc
->HelpString
)
9645 recorded_size
+= 2 * sizeof(INT
);
9646 else if(desc
->HelpContext
!= 0)
9647 recorded_size
+= sizeof(INT
);
9649 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9652 if(!recorded_size
&& !extra_size
)
9655 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9657 aux_seg
->len
+= recorded_size
+ extra_size
;
9659 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9662 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9664 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9666 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9668 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9671 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9672 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9673 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9674 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9676 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9677 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9678 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9679 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9682 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9687 * ^has_param_defaults
9688 * ^oEntry_is_intresource
9690 funcrecord
->FKCCIC
=
9691 desc
->funcdesc
.funckind
|
9692 (desc
->funcdesc
.invkind
<< 3) |
9693 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9694 (desc
->funcdesc
.callconv
<< 8);
9696 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9697 funcrecord
->FKCCIC
|= 0x2000;
9699 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9700 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9701 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9702 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9705 if(paramdefault_size
> 0)
9706 funcrecord
->FKCCIC
|= 0x1000;
9708 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9709 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9711 /* optional fields */
9713 if(!list_empty(&desc
->custdata_list
)){
9714 size
+= 7 * sizeof(INT
);
9715 funcrecord
->HelpContext
= desc
->helpcontext
;
9716 if(desc
->HelpString
)
9717 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9719 funcrecord
->oHelpString
= -1;
9721 funcrecord
->oEntry
= -1;
9722 else if(IS_INTRESOURCE(desc
->Entry
))
9723 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9725 funcrecord
->oEntry
= desc
->Entry
->offset
;
9726 funcrecord
->res9
= -1;
9727 funcrecord
->resA
= -1;
9728 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9729 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9730 }else if(desc
->HelpStringContext
!= 0){
9731 size
+= 6 * sizeof(INT
);
9732 funcrecord
->HelpContext
= desc
->helpcontext
;
9733 if(desc
->HelpString
)
9734 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9736 funcrecord
->oHelpString
= -1;
9738 funcrecord
->oEntry
= -1;
9739 else if(IS_INTRESOURCE(desc
->Entry
))
9740 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9742 funcrecord
->oEntry
= desc
->Entry
->offset
;
9743 funcrecord
->res9
= -1;
9744 funcrecord
->resA
= -1;
9745 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9746 }else if(desc
->Entry
){
9747 size
+= 3 * sizeof(INT
);
9748 funcrecord
->HelpContext
= desc
->helpcontext
;
9749 if(desc
->HelpString
)
9750 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9752 funcrecord
->oHelpString
= -1;
9754 funcrecord
->oEntry
= -1;
9755 else if(IS_INTRESOURCE(desc
->Entry
))
9756 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9758 funcrecord
->oEntry
= desc
->Entry
->offset
;
9759 }else if(desc
->HelpString
){
9760 size
+= 2 * sizeof(INT
);
9761 funcrecord
->HelpContext
= desc
->helpcontext
;
9762 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9763 }else if(desc
->helpcontext
){
9764 size
+= sizeof(INT
);
9765 funcrecord
->HelpContext
= desc
->helpcontext
;
9768 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9769 size
+= paramdefault_size
;
9771 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9772 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9774 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9775 if(desc
->pParamDesc
[j
].Name
)
9776 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9779 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9781 if(paramdefault_size
){
9782 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9783 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9784 else if(paramdefault_size
)
9789 size
+= sizeof(MSFT_ParameterInfo
);
9792 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9798 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9801 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9802 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9803 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9804 DWORD size
= 5 * sizeof(INT
);
9806 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9807 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9808 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9809 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9811 if(desc
->vardesc
.varkind
== VAR_CONST
){
9812 varrecord
->vardescsize
+= sizeof(VARIANT
);
9813 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9815 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9818 if(desc
->HelpStringContext
!= 0){
9819 size
+= 5 * sizeof(INT
);
9820 varrecord
->HelpContext
= desc
->HelpContext
;
9821 if(desc
->HelpString
)
9822 varrecord
->HelpString
= desc
->HelpString
->offset
;
9824 varrecord
->HelpString
= -1;
9825 varrecord
->res9
= -1;
9826 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9827 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9828 }else if(!list_empty(&desc
->custdata_list
)){
9829 size
+= 4 * sizeof(INT
);
9830 varrecord
->HelpContext
= desc
->HelpContext
;
9831 if(desc
->HelpString
)
9832 varrecord
->HelpString
= desc
->HelpString
->offset
;
9834 varrecord
->HelpString
= -1;
9835 varrecord
->res9
= -1;
9836 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9837 }else if(desc
->HelpString
){
9838 size
+= 2 * sizeof(INT
);
9839 varrecord
->HelpContext
= desc
->HelpContext
;
9840 if(desc
->HelpString
)
9841 varrecord
->HelpString
= desc
->HelpString
->offset
;
9843 varrecord
->HelpString
= -1;
9844 }else if(desc
->HelpContext
!= 0){
9845 size
+= sizeof(INT
);
9846 varrecord
->HelpContext
= desc
->HelpContext
;
9849 varrecord
->Info
= size
| (i
<< 16);
9855 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9858 memid
= (MEMBERID
*)varrecord
;
9859 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9860 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9861 *memid
= desc
->funcdesc
.memid
;
9864 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9865 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9866 *memid
= desc
->vardesc
.memid
;
9870 name
= (DWORD
*)memid
;
9871 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9872 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9874 *name
= desc
->Name
->offset
;
9879 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9880 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9882 *name
= desc
->Name
->offset
;
9891 typedef struct tagWMSFT_RefChunk
{
9898 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9900 DWORD offs
= file
->ref_seg
.len
, i
;
9901 WMSFT_RefChunk
*chunk
;
9903 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9904 if(!file
->ref_seg
.data
)
9905 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9907 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9909 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9911 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9912 chunk
->href
= info
->impltypes
[i
].hRef
;
9913 chunk
->res04
= info
->impltypes
[i
].implflags
;
9915 if(i
< info
->typeattr
.cImplTypes
- 1)
9916 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9925 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9929 size
= sizeof(MSFT_TypeInfoBase
);
9932 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9933 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9934 base
->typekind
= TKIND_DISPATCH
;
9936 base
->typekind
= info
->typeattr
.typekind
;
9937 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9938 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
9939 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9944 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
9950 base
->posguid
= info
->guid
->offset
;
9953 base
->flags
= info
->typeattr
.wTypeFlags
;
9955 base
->NameOffset
= info
->Name
->offset
;
9957 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9958 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9960 base
->NameOffset
= -1;
9962 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
9964 base
->docstringoffs
= info
->DocString
->offset
;
9966 base
->docstringoffs
= -1;
9967 base
->helpstringcontext
= info
->dwHelpStringContext
;
9968 base
->helpcontext
= info
->dwHelpContext
;
9969 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9970 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
9971 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
9972 base
->size
= info
->typeattr
.cbSizeInstance
;
9973 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
9974 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9975 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
9976 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9977 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
9979 base
->datatype1
= info
->DllName
->offset
;
9981 base
->datatype1
= -1;
9983 if(info
->typeattr
.cImplTypes
> 0)
9984 base
->datatype1
= info
->impltypes
[0].hRef
;
9986 base
->datatype1
= -1;
9988 base
->datatype2
= index
; /* FIXME: i think there's more here */
9996 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
10000 file
->typeinfo_seg
.len
= 0;
10001 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10002 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
10003 *junk
= file
->typeinfo_seg
.len
;
10005 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
10008 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
10009 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
10011 file
->aux_seg
.len
= 0;
10012 file
->aux_seg
.data
= NULL
;
10014 file
->typeinfo_seg
.len
= 0;
10015 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10016 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
10017 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
10018 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
10022 typedef struct tagWMSFT_ImpFile
{
10028 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10031 WMSFT_ImpFile
*impfile
;
10033 DWORD last_offs
= 0;
10035 file
->impfile_seg
.len
= 0;
10036 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10040 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10044 path
= implib
->name
;
10045 size
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
), NULL
, 0, NULL
, NULL
);
10047 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10050 size
+= sizeof(INT16
);
10052 size
= (size
+ 4) & ~0x3;
10056 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
10059 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
10061 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10062 int strlen
= 0, size
;
10064 impfile
= (WMSFT_ImpFile
*)data
;
10065 impfile
->guid_offs
= implib
->guid
->offset
;
10066 impfile
->lcid
= implib
->lcid
;
10067 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
10069 data
+= sizeof(WMSFT_ImpFile
);
10072 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10076 path
= implib
->name
;
10077 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
),
10078 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
10080 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10083 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
10085 size
= strlen
+ sizeof(INT16
);
10087 size
= (size
+ 4) & ~0x3;
10090 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
10093 implib
->offset
= last_offs
;
10094 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
10098 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10100 MSFT_ImpInfo
*info
;
10101 TLBRefType
*ref_type
;
10104 WMSFT_compile_impfile(This
, file
);
10106 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
10107 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
10109 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
10110 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
10111 if(ref_type
->index
== TLB_REF_USE_GUID
){
10112 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
10113 info
->oGuid
= ref_type
->guid
->offset
;
10115 info
->oGuid
= ref_type
->index
;
10116 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
10122 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10124 file
->guidhash_seg
.len
= 0x80;
10125 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
10126 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
10129 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10131 file
->namehash_seg
.len
= 0x200;
10132 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
10133 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
10136 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
10138 if(contents
&& contents
->len
){
10139 segdir
->offset
= *running_offset
;
10140 segdir
->length
= contents
->len
;
10141 *running_offset
+= segdir
->length
;
10143 segdir
->offset
= -1;
10144 segdir
->length
= 0;
10147 /* TODO: do these ever change? */
10148 segdir
->res08
= -1;
10149 segdir
->res0c
= 0xf;
10152 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10156 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10159 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10163 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10165 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10166 base
->memoffset
+= file_len
;
10173 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10175 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
10176 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
10177 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
10178 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
10179 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
10180 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
10181 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
10182 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
10183 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
10184 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
10185 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
10186 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
10187 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
10188 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
10191 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10193 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10194 WMSFT_TLBFile file
;
10195 DWORD written
, junk_size
, junk_offs
, running_offset
;
10202 TRACE("%p\n", This
);
10204 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10205 if(This
->typeinfos
[i
]->needs_layout
)
10206 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10208 memset(&file
, 0, sizeof(file
));
10210 file
.header
.magic1
= 0x5446534D;
10211 file
.header
.magic2
= 0x00010002;
10212 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10213 file
.header
.lcid2
= This
->set_lcid
;
10214 file
.header
.varflags
= 0x40 | This
->syskind
;
10215 if (This
->HelpFile
)
10216 file
.header
.varflags
|= 0x10;
10217 if (This
->HelpStringDll
)
10218 file
.header
.varflags
|= HELPDLLFLAG
;
10219 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10220 file
.header
.flags
= This
->libflags
;
10221 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10222 file
.header
.helpcontext
= This
->dwHelpContext
;
10223 file
.header
.res44
= 0x20;
10224 file
.header
.res48
= 0x80;
10225 file
.header
.dispatchpos
= This
->dispatch_href
;
10227 WMSFT_compile_namehash(This
, &file
);
10228 /* do name and string compilation to get offsets for other compilations */
10229 hres
= WMSFT_compile_names(This
, &file
);
10231 WMSFT_free_file(&file
);
10235 hres
= WMSFT_compile_strings(This
, &file
);
10237 WMSFT_free_file(&file
);
10241 WMSFT_compile_guidhash(This
, &file
);
10242 hres
= WMSFT_compile_guids(This
, &file
);
10244 WMSFT_free_file(&file
);
10249 file
.header
.helpfile
= This
->HelpFile
->offset
;
10251 file
.header
.helpfile
= -1;
10253 if(This
->DocString
)
10254 file
.header
.helpstring
= This
->DocString
->offset
;
10256 file
.header
.helpstring
= -1;
10258 /* do some more segment compilation */
10259 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10260 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10263 file
.header
.NameOffset
= This
->Name
->offset
;
10265 file
.header
.NameOffset
= -1;
10267 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10270 file
.header
.posguid
= This
->guid
->offset
;
10272 file
.header
.posguid
= -1;
10274 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10275 if(file
.header
.varflags
& HELPDLLFLAG
)
10276 junk_size
+= sizeof(DWORD
);
10278 junk
= heap_alloc_zero(junk_size
);
10279 if(file
.header
.varflags
& HELPDLLFLAG
){
10280 *junk
= This
->HelpStringDll
->offset
;
10289 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10290 WMSFT_compile_impinfo(This
, &file
);
10292 running_offset
= 0;
10294 TRACE("header at: 0x%lx\n", running_offset
);
10295 running_offset
+= sizeof(file
.header
);
10297 TRACE("junk at: 0x%lx\n", running_offset
);
10298 running_offset
+= junk_size
;
10300 TRACE("segdir at: 0x%lx\n", running_offset
);
10301 running_offset
+= sizeof(file
.segdir
);
10303 TRACE("typeinfo at: 0x%lx\n", running_offset
);
10304 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10306 TRACE("guidhashtab at: 0x%lx\n", running_offset
);
10307 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10309 TRACE("guidtab at: 0x%lx\n", running_offset
);
10310 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10312 TRACE("reftab at: 0x%lx\n", running_offset
);
10313 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10315 TRACE("impinfo at: 0x%lx\n", running_offset
);
10316 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10318 TRACE("impfiles at: 0x%lx\n", running_offset
);
10319 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10321 TRACE("namehashtab at: 0x%lx\n", running_offset
);
10322 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10324 TRACE("nametab at: 0x%lx\n", running_offset
);
10325 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10327 TRACE("stringtab at: 0x%lx\n", running_offset
);
10328 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10330 TRACE("typdesc at: 0x%lx\n", running_offset
);
10331 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10333 TRACE("arraydescriptions at: 0x%lx\n", running_offset
);
10334 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10336 TRACE("custdata at: 0x%lx\n", running_offset
);
10337 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10339 TRACE("cdguids at: 0x%lx\n", running_offset
);
10340 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10342 TRACE("res0e at: 0x%lx\n", running_offset
);
10343 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10345 TRACE("res0f at: 0x%lx\n", running_offset
);
10346 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10348 TRACE("aux_seg at: 0x%lx\n", running_offset
);
10350 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10352 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10353 FILE_ATTRIBUTE_NORMAL
, 0);
10354 if (outfile
== INVALID_HANDLE_VALUE
){
10355 WMSFT_free_file(&file
);
10357 return TYPE_E_IOERROR
;
10360 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10362 WMSFT_free_file(&file
);
10363 CloseHandle(outfile
);
10365 return TYPE_E_IOERROR
;
10368 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10371 WMSFT_free_file(&file
);
10372 CloseHandle(outfile
);
10373 return TYPE_E_IOERROR
;
10376 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10378 WMSFT_free_file(&file
);
10379 CloseHandle(outfile
);
10380 return TYPE_E_IOERROR
;
10383 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10384 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10385 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10386 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10387 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10388 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10389 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10390 WMSFT_write_segment(outfile
, &file
.name_seg
);
10391 WMSFT_write_segment(outfile
, &file
.string_seg
);
10392 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10393 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10394 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10395 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10396 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10398 WMSFT_free_file(&file
);
10400 CloseHandle(outfile
);
10405 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10408 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10409 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10413 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10414 REFGUID guid
, VARIANT
*varVal
)
10416 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10419 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10421 if (!guid
|| !varVal
)
10422 return E_INVALIDARG
;
10424 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10426 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10429 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10430 ULONG helpStringContext
)
10432 FIXME("%p, %lu - stub\n", iface
, helpStringContext
);
10436 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10439 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10440 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10443 return E_INVALIDARG
;
10445 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10450 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10451 ICreateTypeLib2_fnQueryInterface
,
10452 ICreateTypeLib2_fnAddRef
,
10453 ICreateTypeLib2_fnRelease
,
10454 ICreateTypeLib2_fnCreateTypeInfo
,
10455 ICreateTypeLib2_fnSetName
,
10456 ICreateTypeLib2_fnSetVersion
,
10457 ICreateTypeLib2_fnSetGuid
,
10458 ICreateTypeLib2_fnSetDocString
,
10459 ICreateTypeLib2_fnSetHelpFileName
,
10460 ICreateTypeLib2_fnSetHelpContext
,
10461 ICreateTypeLib2_fnSetLcid
,
10462 ICreateTypeLib2_fnSetLibFlags
,
10463 ICreateTypeLib2_fnSaveAllChanges
,
10464 ICreateTypeLib2_fnDeleteTypeInfo
,
10465 ICreateTypeLib2_fnSetCustData
,
10466 ICreateTypeLib2_fnSetHelpStringContext
,
10467 ICreateTypeLib2_fnSetHelpStringDll
10470 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10471 REFIID riid
, void **object
)
10473 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10475 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10478 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10480 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10482 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10485 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10487 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10489 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10492 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10495 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10497 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10499 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10504 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10507 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10511 TRACE("%p %x\n", This
, typeFlags
);
10513 if (typeFlags
& TYPEFLAG_FDUAL
) {
10515 ITypeInfo
*dispatch
;
10519 hres
= LoadTypeLib(L
"stdole2.tlb", &stdole
);
10523 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10524 ITypeLib_Release(stdole
);
10528 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10529 ITypeInfo_Release(dispatch
);
10534 old_flags
= This
->typeattr
.wTypeFlags
;
10535 This
->typeattr
.wTypeFlags
= typeFlags
;
10537 hres
= ICreateTypeInfo2_LayOut(iface
);
10538 if (FAILED(hres
)) {
10539 This
->typeattr
.wTypeFlags
= old_flags
;
10546 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10549 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10551 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10554 return E_INVALIDARG
;
10556 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10561 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10564 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10566 TRACE("%p, %ld.\n", iface
, helpContext
);
10568 This
->dwHelpContext
= helpContext
;
10573 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10574 WORD majorVerNum
, WORD minorVerNum
)
10576 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10578 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10580 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10581 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10586 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10587 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10589 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10591 ITypeLib
*container
;
10592 TLBRefType
*ref_type
;
10594 TYPEATTR
*typeattr
;
10598 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10600 if (!typeInfo
|| !refType
)
10601 return E_INVALIDARG
;
10603 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10607 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10608 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10610 ITypeLib_Release(container
);
10612 *refType
= target
->hreftype
;
10617 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10618 if (FAILED(hres
)) {
10619 ITypeLib_Release(container
);
10623 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10624 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10625 implib
->lcid
== libattr
->lcid
&&
10626 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10627 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10631 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10632 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10634 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10635 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10636 implib
->name
= SysAllocString(our_container
->path
);
10638 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10639 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10641 implib
->name
= NULL
;
10642 TRACE("QueryPathOfRegTypeLib failed, no name stored: %#lx.\n", hres
);
10646 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10647 implib
->lcid
= libattr
->lcid
;
10648 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10649 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10651 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10654 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10655 ITypeLib_Release(container
);
10657 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10662 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10663 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10664 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10665 ref_type
->tkind
== typeattr
->typekind
)
10670 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10671 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10673 ref_type
->tkind
= typeattr
->typekind
;
10674 ref_type
->pImpTLInfo
= implib
;
10675 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10677 ref_type
->index
= TLB_REF_USE_GUID
;
10679 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10681 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10684 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10686 *refType
= ref_type
->reference
| 0x1;
10688 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10689 This
->pTypeLib
->dispatch_href
= *refType
;
10694 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10695 UINT index
, FUNCDESC
*funcDesc
)
10697 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10698 TLBFuncDesc tmp_func_desc
, *func_desc
;
10703 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10705 if (!funcDesc
|| funcDesc
->oVft
& 3)
10706 return E_INVALIDARG
;
10708 switch (This
->typeattr
.typekind
) {
10710 if (funcDesc
->funckind
!= FUNC_STATIC
)
10711 return TYPE_E_BADMODULEKIND
;
10713 case TKIND_DISPATCH
:
10714 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10715 return TYPE_E_BADMODULEKIND
;
10718 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10719 return TYPE_E_BADMODULEKIND
;
10722 if (index
> This
->typeattr
.cFuncs
)
10723 return TYPE_E_ELEMENTNOTFOUND
;
10725 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10726 !funcDesc
->cParams
)
10727 return TYPE_E_INCONSISTENTPROPFUNCS
;
10730 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10731 funcDesc
->oVft
% 8 != 0)
10732 return E_INVALIDARG
;
10735 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10736 TLBFuncDesc_Constructor(&tmp_func_desc
);
10738 tmp_func_desc
.funcdesc
= *funcDesc
;
10740 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10741 tmp_func_desc
.funcdesc
.oVft
|= 1;
10743 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10744 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10745 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10747 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10748 tmp_func_desc
.funcdesc
.cScodes
= 0;
10751 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10752 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10753 buf_size
+= sizeof(ELEMDESC
);
10754 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10756 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10757 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10759 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10760 if (FAILED(hres
)) {
10761 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10762 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10766 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10767 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10768 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10769 if (FAILED(hres
)) {
10770 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10771 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10774 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10775 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10776 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10777 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10778 if (FAILED(hres
)) {
10779 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10780 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10786 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10788 if (This
->funcdescs
) {
10789 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10790 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10792 if (index
< This
->typeattr
.cFuncs
) {
10793 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10794 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10795 func_desc
= This
->funcdescs
+ index
;
10797 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10799 /* move custdata lists to the new memory location */
10800 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10802 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
10805 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10807 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10808 list_init(&func_desc
->custdata_list
);
10810 ++This
->typeattr
.cFuncs
;
10812 This
->needs_layout
= TRUE
;
10817 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10818 UINT index
, HREFTYPE refType
)
10820 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10821 TLBImplType
*impl_type
;
10824 TRACE("%p, %u, %ld.\n", iface
, index
, refType
);
10826 switch(This
->typeattr
.typekind
){
10827 case TKIND_COCLASS
: {
10829 FIXME("Unhandled index: -1\n");
10833 if(index
!= This
->typeattr
.cImplTypes
)
10834 return TYPE_E_ELEMENTNOTFOUND
;
10838 case TKIND_INTERFACE
:
10839 case TKIND_DISPATCH
:
10840 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10841 return TYPE_E_ELEMENTNOTFOUND
;
10844 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10848 if (This
->impltypes
){
10851 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10852 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10854 if (index
< This
->typeattr
.cImplTypes
) {
10855 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10856 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10857 impl_type
= This
->impltypes
+ index
;
10859 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10861 /* move custdata lists to the new memory location */
10862 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10864 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
10867 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10869 memset(impl_type
, 0, sizeof(TLBImplType
));
10870 TLBImplType_Constructor(impl_type
);
10871 impl_type
->hRef
= refType
;
10873 ++This
->typeattr
.cImplTypes
;
10875 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10876 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10878 hres
= ICreateTypeInfo2_LayOut(iface
);
10885 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10886 UINT index
, INT implTypeFlags
)
10888 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10889 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10891 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10893 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10894 return TYPE_E_BADMODULEKIND
;
10896 if (index
>= This
->typeattr
.cImplTypes
)
10897 return TYPE_E_ELEMENTNOTFOUND
;
10899 impl_type
->implflags
= implTypeFlags
;
10904 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10907 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10909 TRACE("%p %d\n", This
, alignment
);
10911 This
->typeattr
.cbAlignment
= alignment
;
10916 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10919 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10921 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10924 return E_INVALIDARG
;
10926 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10928 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10933 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10934 UINT index
, VARDESC
*varDesc
)
10936 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10937 TLBVarDesc
*var_desc
;
10940 TRACE("%p %u %p\n", This
, index
, varDesc
);
10942 if (This
->vardescs
){
10945 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10946 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
10948 if (index
< This
->typeattr
.cVars
) {
10949 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10950 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
10951 var_desc
= This
->vardescs
+ index
;
10953 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
10955 /* move custdata lists to the new memory location */
10956 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
10958 TLB_relink_custdata(&This
->vardescs
[i
].custdata_list
);
10961 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10963 TLBVarDesc_Constructor(var_desc
);
10964 hr
= TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10967 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10969 ++This
->typeattr
.cVars
;
10971 This
->needs_layout
= TRUE
;
10976 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10977 UINT index
, LPOLESTR
*names
, UINT numNames
)
10979 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10980 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10983 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10986 return E_INVALIDARG
;
10988 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
10989 return TYPE_E_ELEMENTNOTFOUND
;
10991 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10992 if(numNames
> func_desc
->funcdesc
.cParams
)
10993 return TYPE_E_ELEMENTNOTFOUND
;
10995 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10996 return TYPE_E_ELEMENTNOTFOUND
;
10998 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
10999 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
11000 if (iter
->Name
&& !wcscmp(TLB_get_bstr(iter
->Name
), *names
)) {
11001 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
11002 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
11003 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
11005 return TYPE_E_AMBIGUOUSNAME
;
11009 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
11011 for (i
= 1; i
< numNames
; ++i
) {
11012 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
11013 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
11019 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
11020 UINT index
, LPOLESTR name
)
11022 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11024 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
11027 return E_INVALIDARG
;
11029 if(index
>= This
->typeattr
.cVars
)
11030 return TYPE_E_ELEMENTNOTFOUND
;
11032 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11036 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
11037 TYPEDESC
*tdescAlias
)
11039 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11042 TRACE("%p %p\n", This
, tdescAlias
);
11045 return E_INVALIDARG
;
11047 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
11048 return TYPE_E_BADMODULEKIND
;
11050 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
11054 heap_free(This
->tdescAlias
);
11055 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
11056 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
11061 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
11062 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
11064 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11065 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
11069 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
11070 UINT index
, LPOLESTR docString
)
11072 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11073 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11075 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11078 return E_INVALIDARG
;
11080 if(index
>= This
->typeattr
.cFuncs
)
11081 return TYPE_E_ELEMENTNOTFOUND
;
11083 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11088 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
11089 UINT index
, LPOLESTR docString
)
11091 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11092 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11094 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11097 return E_INVALIDARG
;
11099 if(index
>= This
->typeattr
.cVars
)
11100 return TYPE_E_ELEMENTNOTFOUND
;
11102 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11107 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
11108 UINT index
, DWORD helpContext
)
11110 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11111 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11113 TRACE("%p, %u, %ld.\n", iface
, index
, helpContext
);
11115 if(index
>= This
->typeattr
.cFuncs
)
11116 return TYPE_E_ELEMENTNOTFOUND
;
11118 func_desc
->helpcontext
= helpContext
;
11123 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
11124 UINT index
, DWORD helpContext
)
11126 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11127 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11129 TRACE("%p, %u, %ld.\n", iface
, index
, helpContext
);
11131 if(index
>= This
->typeattr
.cVars
)
11132 return TYPE_E_ELEMENTNOTFOUND
;
11134 var_desc
->HelpContext
= helpContext
;
11139 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
11140 UINT index
, BSTR bstrMops
)
11142 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11143 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
11147 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
11150 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11152 TRACE("%p %p\n", This
, idlDesc
);
11155 return E_INVALIDARG
;
11157 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11158 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11163 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11165 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11166 ITypeInfo2
*tinfo
= &This
->ITypeInfo2_iface
;
11167 TLBFuncDesc
*func_desc
;
11168 UINT user_vft
= 0, i
, depth
= 0;
11169 HRESULT hres
= S_OK
;
11171 TRACE("%p\n", This
);
11173 This
->needs_layout
= FALSE
;
11175 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11180 hres
= ITypeInfo2_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11182 if (SUCCEEDED(hres
)) {
11183 hres
= ITypeInfo2_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11185 if (SUCCEEDED(hres
)) {
11186 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11187 if (FAILED(hres
)) {
11188 ITypeInfo_Release(inh
);
11191 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11192 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11196 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11197 if(SUCCEEDED(hres
)){
11199 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11200 if(SUCCEEDED(hres
)){
11201 ITypeInfo_Release(inh
);
11205 }while(SUCCEEDED(hres
));
11208 ITypeInfo_Release(inh
);
11209 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11210 This
->typeattr
.cbSizeVft
= 0;
11214 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11215 This
->typeattr
.cbSizeVft
= 0;
11219 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11220 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11222 This
->typeattr
.cbSizeVft
= 0;
11224 func_desc
= This
->funcdescs
;
11226 while (i
< This
->typeattr
.cFuncs
) {
11227 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11228 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11230 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11231 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11233 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11235 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11238 BOOL reset
= FALSE
;
11240 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11242 iter
= This
->funcdescs
;
11243 while (j
< This
->typeattr
.cFuncs
) {
11244 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11246 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11249 ++func_desc
->funcdesc
.memid
;
11250 iter
= This
->funcdescs
;
11263 if (user_vft
> This
->typeattr
.cbSizeVft
)
11264 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11266 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11267 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11268 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11270 BOOL reset
= FALSE
;
11273 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11275 iter
= This
->vardescs
;
11276 while (j
< This
->typeattr
.cVars
) {
11277 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11279 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11282 ++var_desc
->vardesc
.memid
;
11283 iter
= This
->vardescs
;
11296 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11299 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11302 TRACE("%p %u\n", This
, index
);
11304 if (index
>= This
->typeattr
.cFuncs
)
11305 return TYPE_E_ELEMENTNOTFOUND
;
11307 typeinfo_release_funcdesc(&This
->funcdescs
[index
]);
11309 --This
->typeattr
.cFuncs
;
11310 if (index
!= This
->typeattr
.cFuncs
)
11312 memmove(This
->funcdescs
+ index
, This
->funcdescs
+ index
+ 1,
11313 sizeof(*This
->funcdescs
) * (This
->typeattr
.cFuncs
- index
));
11314 for (i
= index
; i
< This
->typeattr
.cFuncs
; ++i
)
11315 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
11318 This
->needs_layout
= TRUE
;
11323 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11324 MEMBERID memid
, INVOKEKIND invKind
)
11326 FIXME("%p, %#lx, %d - stub\n", iface
, memid
, invKind
);
11330 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11333 FIXME("%p, %u - stub\n", iface
, index
);
11337 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11340 FIXME("%p, %#lx - stub\n", iface
, memid
);
11344 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11347 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11350 TRACE("%p %u\n", This
, index
);
11352 if (index
>= This
->typeattr
.cImplTypes
)
11353 return TYPE_E_ELEMENTNOTFOUND
;
11355 TLB_FreeCustData(&This
->impltypes
[index
].custdata_list
);
11356 --This
->typeattr
.cImplTypes
;
11358 if (index
< This
->typeattr
.cImplTypes
)
11360 memmove(This
->impltypes
+ index
, This
->impltypes
+ index
+ 1, (This
->typeattr
.cImplTypes
- index
) *
11361 sizeof(*This
->impltypes
));
11362 for (i
= index
; i
< This
->typeattr
.cImplTypes
; ++i
)
11363 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
11369 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11370 REFGUID guid
, VARIANT
*varVal
)
11374 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11376 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11378 if (!guid
|| !varVal
)
11379 return E_INVALIDARG
;
11381 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11383 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11386 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11387 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11389 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11390 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11394 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11395 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11397 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11398 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11402 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11403 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11405 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11406 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11410 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11411 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11413 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11414 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11418 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11419 ULONG helpStringContext
)
11421 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11423 TRACE("%p, %lu.\n", iface
, helpStringContext
);
11425 This
->dwHelpStringContext
= helpStringContext
;
11430 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11431 UINT index
, ULONG helpStringContext
)
11433 FIXME("%p, %u, %lu - stub\n", iface
, index
, helpStringContext
);
11437 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11438 UINT index
, ULONG helpStringContext
)
11440 FIXME("%p, %u, %lu - stub\n", iface
, index
, helpStringContext
);
11444 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11446 FIXME("%p - stub\n", iface
);
11450 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11453 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11455 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11458 return E_INVALIDARG
;
11460 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11465 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11466 ICreateTypeInfo2_fnQueryInterface
,
11467 ICreateTypeInfo2_fnAddRef
,
11468 ICreateTypeInfo2_fnRelease
,
11469 ICreateTypeInfo2_fnSetGuid
,
11470 ICreateTypeInfo2_fnSetTypeFlags
,
11471 ICreateTypeInfo2_fnSetDocString
,
11472 ICreateTypeInfo2_fnSetHelpContext
,
11473 ICreateTypeInfo2_fnSetVersion
,
11474 ICreateTypeInfo2_fnAddRefTypeInfo
,
11475 ICreateTypeInfo2_fnAddFuncDesc
,
11476 ICreateTypeInfo2_fnAddImplType
,
11477 ICreateTypeInfo2_fnSetImplTypeFlags
,
11478 ICreateTypeInfo2_fnSetAlignment
,
11479 ICreateTypeInfo2_fnSetSchema
,
11480 ICreateTypeInfo2_fnAddVarDesc
,
11481 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11482 ICreateTypeInfo2_fnSetVarName
,
11483 ICreateTypeInfo2_fnSetTypeDescAlias
,
11484 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11485 ICreateTypeInfo2_fnSetFuncDocString
,
11486 ICreateTypeInfo2_fnSetVarDocString
,
11487 ICreateTypeInfo2_fnSetFuncHelpContext
,
11488 ICreateTypeInfo2_fnSetVarHelpContext
,
11489 ICreateTypeInfo2_fnSetMops
,
11490 ICreateTypeInfo2_fnSetTypeIdldesc
,
11491 ICreateTypeInfo2_fnLayOut
,
11492 ICreateTypeInfo2_fnDeleteFuncDesc
,
11493 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11494 ICreateTypeInfo2_fnDeleteVarDesc
,
11495 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11496 ICreateTypeInfo2_fnDeleteImplType
,
11497 ICreateTypeInfo2_fnSetCustData
,
11498 ICreateTypeInfo2_fnSetFuncCustData
,
11499 ICreateTypeInfo2_fnSetParamCustData
,
11500 ICreateTypeInfo2_fnSetVarCustData
,
11501 ICreateTypeInfo2_fnSetImplTypeCustData
,
11502 ICreateTypeInfo2_fnSetHelpStringContext
,
11503 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11504 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11505 ICreateTypeInfo2_fnInvalidate
,
11506 ICreateTypeInfo2_fnSetName
11509 /******************************************************************************
11510 * ClearCustData (OLEAUT32.171)
11512 * Clear a custom data type's data.
11515 * lpCust [I] The custom data type instance
11520 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11522 if (lpCust
&& lpCust
->cCustData
)
11524 if (lpCust
->prgCustData
)
11528 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11529 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11531 CoTaskMemFree(lpCust
->prgCustData
);
11532 lpCust
->prgCustData
= NULL
;
11534 lpCust
->cCustData
= 0;