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
;
2256 ptr
= heap_alloc_zero(size
);
2257 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2258 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, size
, NULL
, 0 );
2259 V_BSTR(pVar
)=SysAllocStringLen(NULL
,len
);
2260 MultiByteToWideChar(CP_ACP
, 0, ptr
, size
, V_BSTR(pVar
), len
);
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_SanitizeVariant(VARIANT
*var
)
5739 if (V_VT(var
) == VT_INT
)
5740 return VariantChangeType(var
, var
, 0, VT_I4
);
5741 else if (V_VT(var
) == VT_UINT
)
5742 return VariantChangeType(var
, var
, 0, VT_UI4
);
5747 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5749 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5750 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5753 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5757 SIZE_T size
= sizeof(*src
);
5761 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5762 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5763 for (i
= 0; i
< src
->cParams
; i
++)
5765 size
+= sizeof(ELEMDESC
);
5766 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5769 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5770 if (!dest
) return E_OUTOFMEMORY
;
5773 if (dispinterface
) /* overwrite funckind */
5774 dest
->funckind
= FUNC_DISPATCH
;
5775 buffer
= (char *)(dest
+ 1);
5777 dest
->oVft
= dest
->oVft
& 0xFFFC;
5779 if (dest
->cScodes
) {
5780 dest
->lprgscode
= (SCODE
*)buffer
;
5781 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5782 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5784 dest
->lprgscode
= NULL
;
5786 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5789 SysFreeString((BSTR
)dest
);
5793 if (dest
->cParams
) {
5794 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5795 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5796 for (i
= 0; i
< src
->cParams
; i
++)
5798 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5804 /* undo the above actions */
5805 for (i
= i
- 1; i
>= 0; i
--)
5806 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5807 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5808 SysFreeString((BSTR
)dest
);
5812 dest
->lprgelemdescParam
= NULL
;
5814 /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
5815 * This accounts for several arguments that are separate in the signature of
5816 * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
5817 if (dispinterface
&& (src
->funckind
!= FUNC_DISPATCH
))
5819 /* functions that have a [retval] parameter return this value into pVarResult.
5820 * [retval] is always the last parameter (if present) */
5821 if (dest
->cParams
&&
5822 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5824 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5825 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5827 ERR("elemdesc should have started with VT_PTR instead of:\n");
5829 dump_ELEMDESC(elemdesc
);
5830 return E_UNEXPECTED
;
5833 /* the type pointed to by this [retval] becomes elemdescFunc,
5834 * i.e. the function signature's return type.
5835 * We are using a flat buffer so there is no danger of leaking memory */
5836 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5838 /* remove the last parameter */
5841 else if (dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5842 /* Even if not otherwise replaced HRESULT is returned in pExcepInfo->scode,
5843 * not pVarResult. So the function signature should show no return value. */
5844 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5846 /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
5847 * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
5848 if (dest
->cParams
&& (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FLCID
))
5856 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5858 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5859 if (var_desc
->varkind
== VAR_CONST
)
5860 VariantClear(var_desc
->u
.lpvarValue
);
5861 SysFreeString((BSTR
)var_desc
);
5864 /* internal function to make the inherited interfaces' methods appear
5865 * part of the interface */
5866 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5867 UINT index
, const TLBFuncDesc
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5869 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5871 UINT implemented_funcs
= 0;
5876 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5880 ITypeInfo
*pSubTypeInfo
;
5883 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5887 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5890 &sub_funcs
, hrefoffset
);
5891 implemented_funcs
+= sub_funcs
;
5892 ITypeInfo_Release(pSubTypeInfo
);
5895 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5899 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5903 if (index
< implemented_funcs
)
5904 return E_INVALIDARG
;
5905 index
-= implemented_funcs
;
5907 if (index
>= This
->typeattr
.cFuncs
)
5908 return TYPE_E_ELEMENTNOTFOUND
;
5910 *ppFuncDesc
= &This
->funcdescs
[index
];
5914 static HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const TLBFuncDesc
**func_desc
, UINT
*hrefoffset
)
5916 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5918 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5919 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface
, index
, func_desc
, NULL
, hrefoffset
);
5921 if (index
>= This
->typeattr
.cFuncs
)
5922 return TYPE_E_ELEMENTNOTFOUND
;
5924 *func_desc
= &This
->funcdescs
[index
];
5928 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5930 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5933 switch (pTypeDesc
->vt
)
5935 case VT_USERDEFINED
:
5936 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5940 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5943 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5951 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5954 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5955 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5956 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5959 /* ITypeInfo::GetFuncDesc
5961 * Retrieves the FUNCDESC structure that contains information about a
5962 * specified function.
5965 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5966 LPFUNCDESC
*ppFuncDesc
)
5968 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5969 const TLBFuncDesc
*internal_funcdesc
;
5971 UINT hrefoffset
= 0;
5973 TRACE("(%p) index %d\n", This
, index
);
5976 return E_INVALIDARG
;
5978 if (This
->needs_layout
)
5979 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5981 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5982 &internal_funcdesc
, &hrefoffset
);
5985 WARN("description for function %d not found\n", index
);
5989 hr
= TLB_AllocAndInitFuncDesc(
5990 &internal_funcdesc
->funcdesc
,
5992 This
->typeattr
.typekind
== TKIND_DISPATCH
);
5994 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
5995 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5997 TRACE("-- %#lx.\n", hr
);
6001 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6005 SIZE_T size
= sizeof(*src
);
6008 if (src
->lpstrSchema
) size
+= (lstrlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6009 if (src
->varkind
== VAR_CONST
)
6010 size
+= sizeof(VARIANT
);
6011 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6013 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6014 if (!dest
) return E_OUTOFMEMORY
;
6017 buffer
= (char *)(dest
+ 1);
6018 if (src
->lpstrSchema
)
6021 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6022 len
= lstrlenW(src
->lpstrSchema
);
6023 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6024 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6027 if (src
->varkind
== VAR_CONST
)
6031 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6032 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6033 buffer
+= sizeof(VARIANT
);
6034 VariantInit(dest
->u
.lpvarValue
);
6035 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6038 SysFreeString((BSTR
)dest
);
6042 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6045 if (src
->varkind
== VAR_CONST
)
6046 VariantClear(dest
->u
.lpvarValue
);
6047 SysFreeString((BSTR
)dest
);
6054 /* ITypeInfo::GetVarDesc
6056 * Retrieves a VARDESC structure that describes the specified variable.
6059 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6060 LPVARDESC
*ppVarDesc
)
6062 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6063 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6065 TRACE("(%p) index %d\n", This
, index
);
6067 if(index
>= This
->typeattr
.cVars
)
6068 return TYPE_E_ELEMENTNOTFOUND
;
6070 if (This
->needs_layout
)
6071 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6073 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6076 /* internal function to make the inherited interfaces' methods appear
6077 * part of the interface, remembering if the top-level was dispinterface */
6078 static HRESULT
typeinfo_getnames( ITypeInfo
*iface
, MEMBERID memid
, BSTR
*names
,
6079 UINT max_names
, UINT
*num_names
, BOOL dispinterface
)
6081 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
6082 const TLBFuncDesc
*func_desc
;
6083 const TLBVarDesc
*var_desc
;
6088 func_desc
= TLB_get_funcdesc_by_memberid(This
, memid
);
6091 UINT params
= func_desc
->funcdesc
.cParams
;
6092 if (!max_names
|| !func_desc
->Name
)
6095 *names
= SysAllocString(TLB_get_bstr(func_desc
->Name
));
6098 if (dispinterface
&& (func_desc
->funcdesc
.funckind
!= FUNC_DISPATCH
))
6100 /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc */
6101 if ((params
> 0) && (func_desc
->funcdesc
.lprgelemdescParam
[params
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
6102 --params
; /* Invoke(pVarResult) supplies the [retval] parameter, so it's hidden from DISPPARAMS */
6103 if ((params
> 0) && (func_desc
->funcdesc
.lprgelemdescParam
[params
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FLCID
))
6104 --params
; /* Invoke(lcid) supplies the [lcid] parameter, so it's hidden from DISPPARAMS */
6107 for (i
= 0; i
< params
; i
++)
6109 if (*num_names
>= max_names
|| !func_desc
->pParamDesc
[i
].Name
)
6111 names
[*num_names
] = SysAllocString(TLB_get_bstr(func_desc
->pParamDesc
[i
].Name
));
6117 var_desc
= TLB_get_vardesc_by_memberid(This
, memid
);
6120 *names
= SysAllocString(TLB_get_bstr(var_desc
->Name
));
6125 if (This
->impltypes
&&
6126 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
))
6128 /* recursive search */
6131 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &parent
);
6132 if (SUCCEEDED(result
))
6134 result
= typeinfo_getnames(parent
, memid
, names
, max_names
, num_names
, dispinterface
);
6135 ITypeInfo_Release(parent
);
6138 WARN("Could not search inherited interface!\n");
6142 WARN("no names found\n");
6145 return TYPE_E_ELEMENTNOTFOUND
;
6150 /* ITypeInfo_GetNames
6152 * Retrieves the variable with the specified member ID (or the name of the
6153 * property or method and its parameters) that correspond to the specified
6156 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6157 BSTR
*names
, UINT max_names
, UINT
*num_names
)
6159 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6161 TRACE("%p, %#lx, %p, %d, %p\n", iface
, memid
, names
, max_names
, num_names
);
6163 if (!names
) return E_INVALIDARG
;
6165 return typeinfo_getnames((ITypeInfo
*)iface
, memid
, names
, max_names
, num_names
,
6166 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6169 /* ITypeInfo::GetRefTypeOfImplType
6171 * If a type description describes a COM class, it retrieves the type
6172 * description of the implemented interface types. For an interface,
6173 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6177 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6182 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6185 TRACE("(%p) index %d\n", This
, index
);
6186 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6190 /* only valid on dual interfaces;
6191 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6194 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6200 hr
= TYPE_E_ELEMENTNOTFOUND
;
6203 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6205 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6206 *pRefType
= This
->pTypeLib
->dispatch_href
;
6210 if(index
>= This
->typeattr
.cImplTypes
)
6211 hr
= TYPE_E_ELEMENTNOTFOUND
;
6213 *pRefType
= This
->impltypes
[index
].hRef
;
6214 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6222 TRACE("SUCCESS -- hRef %#lx.\n", *pRefType
);
6224 TRACE("FAILURE -- hresult %#lx.\n", hr
);
6230 /* ITypeInfo::GetImplTypeFlags
6232 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6233 * or base interface in a type description.
6235 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6236 UINT index
, INT
*pImplTypeFlags
)
6238 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6240 TRACE("(%p) index %d\n", This
, index
);
6243 return E_INVALIDARG
;
6245 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6246 *pImplTypeFlags
= 0;
6250 if(index
>= This
->typeattr
.cImplTypes
)
6251 return TYPE_E_ELEMENTNOTFOUND
;
6253 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6259 * Maps between member names and member IDs, and parameter names and
6262 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6263 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6265 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6266 const TLBVarDesc
*pVDesc
;
6270 TRACE("%p, %s, %d.\n", iface
, debugstr_w(*rgszNames
), cNames
);
6272 /* init out parameters in case of failure */
6273 for (i
= 0; i
< cNames
; i
++)
6274 pMemId
[i
] = MEMBERID_NIL
;
6276 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6278 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6279 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6280 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6281 for(i
=1; i
< cNames
; i
++){
6282 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6283 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6285 if( j
<pFDesc
->funcdesc
.cParams
)
6288 ret
=DISP_E_UNKNOWNNAME
;
6290 TRACE("-- %#lx.\n", ret
);
6294 pVDesc
= TLB_get_vardesc_by_name(This
, *rgszNames
);
6297 *pMemId
= pVDesc
->vardesc
.memid
;
6300 /* not found, see if it can be found in an inherited interface */
6301 if(This
->impltypes
) {
6302 /* recursive search */
6304 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6306 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6307 ITypeInfo_Release(pTInfo
);
6310 WARN("Could not search inherited interface!\n");
6312 WARN("no names found\n");
6313 return DISP_E_UNKNOWNNAME
;
6319 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6320 extern double call_double_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6321 __ASM_GLOBAL_FUNC( call_method
,
6323 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6324 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6325 "movl %esp,%ebp\n\t"
6326 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6328 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6330 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6331 "movl 12(%ebp),%edx\n\t"
6332 "movl %esp,%edi\n\t"
6335 "subl %edx,%edi\n\t"
6336 "andl $~15,%edi\n\t"
6337 "movl %edi,%esp\n\t"
6338 "movl 12(%ebp),%ecx\n\t"
6339 "movl 16(%ebp),%esi\n\t"
6342 "1:\tcall *8(%ebp)\n\t"
6343 "subl %esp,%edi\n\t"
6344 "movl 20(%ebp),%ecx\n\t"
6345 "movl %edi,(%ecx)\n\t"
6346 "leal -8(%ebp),%esp\n\t"
6348 __ASM_CFI(".cfi_same_value %edi\n\t")
6350 __ASM_CFI(".cfi_same_value %esi\n\t")
6352 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6353 __ASM_CFI(".cfi_same_value %ebp\n\t")
6355 __ASM_GLOBAL_FUNC( call_double_method
,
6356 "jmp " __ASM_NAME("call_method") )
6358 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6359 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6361 int argspos
= 0, stack_offset
;
6366 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6367 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6368 pvargResult
, V_VT(pvargResult
));
6370 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6372 FIXME("unsupported calling convention %d\n",cc
);
6373 return E_INVALIDARG
;
6376 /* maximum size for an argument is sizeof(VARIANT) */
6377 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6381 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6382 func
= vtable
[oVft
/sizeof(void *)];
6383 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6385 else func
= (void *)oVft
;
6391 args
[argspos
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6394 WARN("invalid return type %u\n", vtReturn
);
6396 return E_INVALIDARG
;
6401 for (i
= 0; i
< cActuals
; i
++)
6403 VARIANT
*arg
= prgpvarg
[i
];
6414 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6415 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6419 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6420 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6422 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6423 args
[argspos
++] = V_BOOL(arg
);
6426 args
[argspos
++] = V_UI4(arg
);
6429 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6437 call_method( func
, argspos
, args
, &stack_offset
);
6440 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6444 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6449 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6452 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6456 if (stack_offset
&& cc
== CC_STDCALL
)
6458 WARN( "stack pointer off by %d\n", stack_offset
);
6459 return DISP_E_BADCALLEE
;
6461 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6462 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6466 #elif defined(__x86_64__)
6468 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6469 extern double CDECL
call_double_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6470 __ASM_GLOBAL_FUNC( call_method
,
6472 __ASM_SEH(".seh_pushreg %rbp\n\t")
6473 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6474 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6475 "movq %rsp,%rbp\n\t"
6476 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6477 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6479 __ASM_SEH(".seh_pushreg %rsi\n\t")
6480 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6482 __ASM_SEH(".seh_pushreg %rdi\n\t")
6483 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6484 __ASM_SEH(".seh_endprologue\n\t")
6485 "movq %rcx,%rax\n\t"
6488 "cmovgq %rdx,%rcx\n\t"
6489 "leaq 0(,%rcx,8),%rdx\n\t"
6490 "subq %rdx,%rsp\n\t"
6491 "andq $~15,%rsp\n\t"
6492 "movq %rsp,%rdi\n\t"
6495 "movq 0(%rsp),%rcx\n\t"
6496 "movq 8(%rsp),%rdx\n\t"
6497 "movq 16(%rsp),%r8\n\t"
6498 "movq 24(%rsp),%r9\n\t"
6499 "movq 0(%rsp),%xmm0\n\t"
6500 "movq 8(%rsp),%xmm1\n\t"
6501 "movq 16(%rsp),%xmm2\n\t"
6502 "movq 24(%rsp),%xmm3\n\t"
6504 "leaq -16(%rbp),%rsp\n\t"
6506 __ASM_CFI(".cfi_same_value %rdi\n\t")
6508 __ASM_CFI(".cfi_same_value %rsi\n\t")
6509 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6511 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6512 __ASM_CFI(".cfi_same_value %rbp\n\t")
6514 __ASM_GLOBAL_FUNC( call_double_method
,
6515 "jmp " __ASM_NAME("call_method") )
6517 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6518 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6525 TRACE("%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d).\n",
6526 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6527 pvargResult
, V_VT(pvargResult
));
6529 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6531 FIXME("unsupported calling convention %d\n",cc
);
6532 return E_INVALIDARG
;
6535 /* maximum size for an argument is sizeof(DWORD_PTR) */
6536 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6540 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6541 func
= vtable
[oVft
/sizeof(void *)];
6542 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6544 else func
= (void *)oVft
;
6550 args
[argspos
++] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6553 WARN("invalid return type %u\n", vtReturn
);
6555 return E_INVALIDARG
;
6560 for (i
= 0; i
< cActuals
; i
++)
6562 VARIANT
*arg
= prgpvarg
[i
];
6568 args
[argspos
++] = (ULONG_PTR
)arg
;
6570 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6571 args
[argspos
++] = V_BOOL(arg
);
6574 args
[argspos
++] = V_UI8(arg
);
6577 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6583 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
);
6587 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
);
6591 call_method( func
, argspos
, args
);
6594 V_UI8(pvargResult
) = call_method( func
, argspos
, args
);
6598 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6599 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6603 #elif defined(__arm__)
6605 extern LONGLONG CDECL
call_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6606 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6607 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6608 __ASM_GLOBAL_FUNC( call_method
,
6611 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6612 * 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)
6615 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6616 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6618 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6619 "beq 1f\n\t" /* Skip allocation if no stack args */
6620 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6621 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6622 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6623 "subs r1, r1, #4\n\t" /* Decrement count */
6624 "bgt 2b\n\t" /* Loop till done */
6628 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6630 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6631 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6633 "blx ip\n\t" /* Call the target function */
6635 "mov sp, fp\n\t" /* Clean the stack using fp */
6636 "pop {fp, pc}\n\t" /* Restore fp and return */
6638 __ASM_GLOBAL_FUNC( call_float_method
,
6639 "b " __ASM_NAME("call_method") )
6640 __ASM_GLOBAL_FUNC( call_double_method
,
6641 "b " __ASM_NAME("call_method") )
6643 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6644 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6659 int rcount
; /* 32-bit register index count */
6661 int scount
= 0; /* single-precision float register index count */
6662 int dcount
= 0; /* double-precision float register index count */
6665 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6666 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6668 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6670 FIXME("unsupported calling convention %d\n",cc
);
6671 return E_INVALIDARG
;
6679 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6680 func
= vtable
[oVft
/sizeof(void *)];
6681 regs
.r
[rcount
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6683 else func
= (void *)oVft
;
6685 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6686 /* first as it will need to be in the 'r' registers: */
6691 regs
.r
[rcount
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6694 WARN("invalid return type %u\n", vtReturn
);
6695 return E_INVALIDARG
;
6696 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6700 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6701 args
= heap_alloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 4 );
6703 for (i
= 0; i
< cActuals
; i
++)
6705 VARIANT
*arg
= prgpvarg
[i
];
6706 DWORD
*pdwarg
= (DWORD
*)(arg
); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6707 int ntemp
; /* Used for counting words split between registers and stack */
6713 case VT_R8
: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6716 dcount
= max( (scount
+ 1) / 2, dcount
);
6719 regs
.sd
.d
[dcount
++] = V_R8(arg
);
6723 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6724 memcpy( &args
[argspos
], &V_R8(arg
), sizeof(V_R8(arg
)) );
6725 argspos
+= sizeof(V_R8(arg
)) / sizeof(DWORD
);
6729 case VT_I8
: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6734 rcount
+= (rcount
% 2); /* align rcount to 8-byte register pair */
6735 memcpy( ®s
.r
[rcount
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6736 rcount
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6740 rcount
= 4; /* Make sure we flag that all 'r' regs are full */
6741 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6742 memcpy( &args
[argspos
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6743 argspos
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6746 case VT_DECIMAL
: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6748 /* 8-byte align 'r' and/or stack: */
6750 rcount
+= (rcount
% 2);
6754 argspos
+= (argspos
% 2);
6756 ntemp
= sizeof(*arg
) / sizeof(DWORD
);
6760 regs
.r
[rcount
++] = *pdwarg
++;
6762 args
[argspos
++] = *pdwarg
++;
6766 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6768 regs
.r
[rcount
++] = V_BOOL(arg
);
6770 args
[argspos
++] = V_BOOL(arg
);
6772 case VT_R4
: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6774 if (!(scount
% 2)) scount
= max( scount
, dcount
* 2 );
6776 regs
.sd
.s
[scount
++] = V_R4(arg
);
6778 args
[argspos
++] = V_UI4(arg
);
6783 regs
.r
[rcount
++] = V_UI4(arg
);
6785 args
[argspos
++] = V_UI4(arg
);
6788 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6791 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 8-byte */
6795 case VT_EMPTY
: /* EMPTY = no return value */
6796 case VT_DECIMAL
: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6798 call_method( func
, argspos
, args
, (DWORD
*)®s
);
6801 V_R4(pvargResult
) = call_float_method( func
, argspos
, args
, (DWORD
*)®s
);
6805 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, (DWORD
*)®s
);
6810 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6813 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6817 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6818 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6822 #elif defined(__aarch64__)
6824 extern DWORD_PTR CDECL
call_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6825 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6826 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6827 __ASM_GLOBAL_FUNC( call_method
,
6828 "stp x29, x30, [sp, #-16]!\n\t"
6830 "sub sp, sp, x1, lsl #3\n\t"
6832 "1:\tsub x1, x1, #1\n\t"
6833 "ldr x4, [x2, x1, lsl #3]\n\t"
6834 "str x4, [sp, x1, lsl #3]\n\t"
6836 "2:\tmov x16, x0\n\t"
6838 "ldp d0, d1, [x9]\n\t"
6839 "ldp d2, d3, [x9, #0x10]\n\t"
6840 "ldp d4, d5, [x9, #0x20]\n\t"
6841 "ldp d6, d7, [x9, #0x30]\n\t"
6842 "ldp x0, x1, [x9, #0x40]\n\t"
6843 "ldp x2, x3, [x9, #0x50]\n\t"
6844 "ldp x4, x5, [x9, #0x60]\n\t"
6845 "ldp x6, x7, [x9, #0x70]\n\t"
6846 "ldr x8, [x9, #0x80]\n\t"
6849 "ldp x29, x30, [sp], #16\n\t"
6851 __ASM_GLOBAL_FUNC( call_float_method
,
6852 "b " __ASM_NAME("call_method") )
6853 __ASM_GLOBAL_FUNC( call_double_method
,
6854 "b " __ASM_NAME("call_method") )
6856 HRESULT WINAPI
DispCallFunc( void *instance
, ULONG_PTR offset
, CALLCONV cc
, VARTYPE ret_type
, UINT count
,
6857 VARTYPE
*types
, VARIANTARG
**vargs
, VARIANT
*result
)
6872 int rcount
; /* 64-bit register index count */
6873 int fpcount
= 0; /* float register index count */
6875 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6876 instance
, offset
, cc
, ret_type
, count
, types
, vargs
, result
, V_VT(result
));
6878 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6880 FIXME("unsupported calling convention %d\n",cc
);
6881 return E_INVALIDARG
;
6889 const FARPROC
*vtable
= *(FARPROC
**)instance
;
6890 func
= vtable
[offset
/sizeof(void *)];
6891 regs
.x
[rcount
++] = (DWORD_PTR
)instance
; /* the This pointer is always the first parameter */
6893 else func
= (void *)offset
;
6895 /* maximum size for an argument is 16 */
6896 args
= heap_alloc( 16 * count
);
6898 for (i
= 0; i
< count
; i
++)
6900 VARIANT
*arg
= vargs
[i
];
6905 if (fpcount
< 8) regs
.fp
[fpcount
++].f
= V_R4(arg
);
6906 else *(float *)&args
[argspos
++] = V_R4(arg
);
6910 if (fpcount
< 8) regs
.fp
[fpcount
++].d
= V_R8(arg
);
6911 else *(double *)&args
[argspos
++] = V_R8(arg
);
6916 memcpy( ®s
.x
[rcount
], arg
, sizeof(*arg
) );
6921 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6926 if (rcount
< 8) regs
.x
[rcount
++] = (DWORD_PTR
)arg
;
6927 else args
[argspos
++] = (DWORD_PTR
)arg
;
6929 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6930 if (rcount
< 8) regs
.x
[rcount
++] = V_BOOL(arg
);
6931 else args
[argspos
++] = V_BOOL(arg
);
6934 if (rcount
< 8) regs
.x
[rcount
++] = V_UI8(arg
);
6935 else args
[argspos
++] = V_UI8(arg
);
6938 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(types
[i
]), debugstr_variant(arg
));
6941 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 16-byte */
6947 return E_INVALIDARG
;
6950 regs
.x
[8] = (DWORD_PTR
)result
; /* x8 is a pointer to the result */
6951 call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6954 V_R4(result
) = call_float_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6958 V_R8(result
) = call_double_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6961 V_UI8(result
) = call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6965 if (ret_type
!= VT_VARIANT
) V_VT(result
) = ret_type
;
6966 TRACE("retval: %s\n", debugstr_variant(result
));
6970 #else /* __aarch64__ */
6972 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6973 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6975 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6976 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6982 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6985 ITypeInfo
*tinfo2
= NULL
;
6986 TYPEATTR
*tattr
= NULL
;
6988 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6991 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, hr %#lx.\n", tdesc
->u
.hreftype
, hr
);
6994 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6997 ERR("ITypeInfo_GetTypeAttr failed, hr %#lx.\n", hr
);
6998 ITypeInfo_Release(tinfo2
);
7002 switch (tattr
->typekind
)
7009 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
7012 case TKIND_INTERFACE
:
7013 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
7019 case TKIND_DISPATCH
:
7028 FIXME("TKIND_RECORD unhandled.\n");
7033 FIXME("TKIND_UNION unhandled.\n");
7038 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
7042 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7043 ITypeInfo_Release(tinfo2
);
7047 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
7051 /* enforce only one level of pointer indirection */
7052 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
7054 tdesc
= tdesc
->u
.lptdesc
;
7056 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7057 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7058 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7059 if ((tdesc
->vt
== VT_USERDEFINED
) ||
7060 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
7062 VARTYPE vt_userdefined
= 0;
7063 const TYPEDESC
*tdesc_userdefined
= tdesc
;
7064 if (tdesc
->vt
== VT_PTR
)
7066 vt_userdefined
= VT_BYREF
;
7067 tdesc_userdefined
= tdesc
->u
.lptdesc
;
7069 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
7071 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
7072 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
7074 *vt
|= vt_userdefined
;
7086 case VT_USERDEFINED
:
7087 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
7094 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
7095 hr
= DISP_E_BADVARTYPE
;
7099 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
7114 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, HREFTYPE href
, GUID
*guid
)
7121 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
7125 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
7127 ITypeInfo_Release(tinfo2
);
7131 switch(tattr
->typekind
) {
7133 hres
= get_iface_guid(tinfo2
, tattr
->tdescAlias
.u
.hreftype
, guid
);
7136 case TKIND_INTERFACE
:
7137 case TKIND_DISPATCH
:
7138 *guid
= tattr
->guid
;
7142 for (i
= 0; i
< tattr
->cImplTypes
; i
++)
7144 ITypeInfo_GetImplTypeFlags(tinfo2
, i
, &flags
);
7145 if (flags
& IMPLTYPEFLAG_FDEFAULT
)
7149 if (i
== tattr
->cImplTypes
)
7152 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo2
, i
, &href
);
7153 if (SUCCEEDED(hres
))
7154 hres
= get_iface_guid(tinfo2
, href
, guid
);
7158 ERR("Unexpected typekind %d\n", tattr
->typekind
);
7159 hres
= E_UNEXPECTED
;
7162 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7163 ITypeInfo_Release(tinfo2
);
7167 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
7169 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
7172 #define INVBUF_ELEMENT_SIZE \
7173 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7174 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7175 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7176 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7177 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7178 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7179 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7180 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7182 static HRESULT WINAPI
ITypeInfo_fnInvoke(
7187 DISPPARAMS
*pDispParams
,
7188 VARIANT
*pVarResult
,
7189 EXCEPINFO
*pExcepInfo
,
7192 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7194 unsigned int var_index
;
7197 const TLBFuncDesc
*pFuncInfo
;
7200 TRACE("%p, %p, %ld, %#x, %p, %p, %p, %p.\n", iface
, pIUnk
, memid
, wFlags
, pDispParams
,
7201 pVarResult
, pExcepInfo
, pArgErr
);
7203 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7204 return DISP_E_MEMBERNOTFOUND
;
7208 ERR("NULL pDispParams not allowed\n");
7209 return E_INVALIDARG
;
7212 dump_DispParms(pDispParams
);
7214 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7216 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7217 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7218 return E_INVALIDARG
;
7221 /* we do this instead of using GetFuncDesc since it will return a fake
7222 * FUNCDESC for dispinterfaces and we want the real function description */
7223 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7224 pFuncInfo
= &This
->funcdescs
[fdc
];
7225 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7226 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7227 !func_restricted( &pFuncInfo
->funcdesc
))
7231 if (fdc
< This
->typeattr
.cFuncs
) {
7232 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7236 TRACE("invoking:\n");
7237 dump_TLBFuncDescOne(pFuncInfo
);
7240 switch (func_desc
->funckind
) {
7241 case FUNC_PUREVIRTUAL
:
7242 case FUNC_VIRTUAL
: {
7243 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7245 VARIANT retval
= {{{0}}}; /* pointer for storing byref retvals in */
7246 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7247 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7248 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7249 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7250 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7251 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7252 UINT vargs_converted
=0;
7257 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7259 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7261 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7262 hres
= DISP_E_PARAMNOTFOUND
;
7267 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7269 ERR("functions with the vararg attribute do not support named arguments\n");
7270 hres
= DISP_E_NONAMEDARGS
;
7274 for (i
= 0; i
< func_desc
->cParams
; i
++)
7276 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7277 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7282 TRACE("changing args\n");
7283 for (i
= 0; i
< func_desc
->cParams
; i
++)
7285 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7286 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7287 VARIANTARG
*src_arg
;
7289 if (wParamFlags
& PARAMFLAG_FLCID
)
7291 prgpvarg
[i
] = &rgvarg
[i
];
7292 V_VT(prgpvarg
[i
]) = VT_I4
;
7293 V_I4(prgpvarg
[i
]) = This
->pTypeLib
->lcid
;
7299 for (j
= 0; j
< cNamedArgs
; j
++)
7301 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7303 src_arg
= &pDispParams
->rgvarg
[j
];
7308 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7310 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7314 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7316 /* under most conditions the caller is not allowed to
7317 * pass in a dispparam arg in the index of what would be
7318 * the retval parameter. however, there is an exception
7319 * where the extra parameter is used in an extra
7320 * IDispatch::Invoke below */
7321 if ((i
< pDispParams
->cArgs
) &&
7322 ((func_desc
->cParams
!= 1) || !pVarResult
||
7323 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7325 hres
= DISP_E_BADPARAMCOUNT
;
7329 /* note: this check is placed so that if the caller passes
7330 * in a VARIANTARG for the retval we just ignore it, like
7332 if (i
== func_desc
->cParams
- 1)
7334 prgpvarg
[i
] = &rgvarg
[i
];
7335 V_BYREF(prgpvarg
[i
]) = &retval
;
7336 V_VT(prgpvarg
[i
]) = rgvt
[i
];
7340 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7341 hres
= E_UNEXPECTED
;
7345 else if (src_arg
&& !((wParamFlags
& PARAMFLAG_FOPT
) &&
7346 V_VT(src_arg
) == VT_ERROR
&& V_ERROR(src_arg
) == DISP_E_PARAMNOTFOUND
))
7348 TRACE("%s\n", debugstr_variant(src_arg
));
7350 if(rgvt
[i
]!=V_VT(src_arg
))
7352 if (rgvt
[i
] == VT_VARIANT
)
7353 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7354 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7356 if (rgvt
[i
] == V_VT(src_arg
))
7357 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7360 if (wParamFlags
& PARAMFLAG_FIN
)
7361 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7362 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7364 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7366 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7368 SAFEARRAYBOUND bound
;
7372 bound
.cElements
= pDispParams
->cArgs
-i
;
7373 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7375 ERR("SafeArrayCreate failed\n");
7378 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7381 ERR("SafeArrayAccessData failed with %#lx.\n", hres
);
7382 SafeArrayDestroy(a
);
7385 for (j
= 0; j
< bound
.cElements
; j
++)
7386 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7387 hres
= SafeArrayUnaccessData(a
);
7390 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres
);
7391 SafeArrayDestroy(a
);
7394 if (rgvt
[i
] & VT_BYREF
)
7395 V_BYREF(&rgvarg
[i
]) = &a
;
7397 V_ARRAY(&rgvarg
[i
]) = a
;
7398 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7400 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7402 if (wParamFlags
& PARAMFLAG_FIN
)
7403 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7405 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7406 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7407 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7409 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7411 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7412 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7416 /* FIXME: this doesn't work for VT_BYREF arguments if
7417 * they are not the same type as in the paramdesc */
7418 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7419 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7420 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7425 ERR("failed to convert param %d to %s from %s\n", i
,
7426 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7429 prgpvarg
[i
] = &rgvarg
[i
];
7433 prgpvarg
[i
] = src_arg
;
7436 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7437 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7438 && V_UNKNOWN(prgpvarg
[i
])) {
7439 IUnknown
*userdefined_iface
;
7442 if (tdesc
->vt
== VT_PTR
)
7443 tdesc
= tdesc
->u
.lptdesc
;
7445 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->u
.hreftype
, &guid
);
7449 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7451 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7455 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7456 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7459 else if (wParamFlags
& PARAMFLAG_FOPT
)
7462 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7463 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7465 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7471 /* if the function wants a pointer to a variant then
7472 * set that up, otherwise just pass the VT_ERROR in
7473 * the argument by value */
7474 if (rgvt
[i
] & VT_BYREF
)
7476 V_VT(&missing_arg
[i
]) = VT_ERROR
;
7477 V_ERROR(&missing_arg
[i
]) = DISP_E_PARAMNOTFOUND
;
7479 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7480 V_VARIANTREF(arg
) = &missing_arg
[i
];
7484 V_VT(arg
) = VT_ERROR
;
7485 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
7491 hres
= DISP_E_BADPARAMCOUNT
;
7495 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7497 /* VT_VOID is a special case for return types, so it is not
7498 * handled in the general function */
7499 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7500 V_VT(&varresult
) = VT_EMPTY
;
7503 V_VT(&varresult
) = 0;
7504 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7505 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7508 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7509 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7510 prgpvarg
, &varresult
);
7512 vargs_converted
= 0;
7514 for (i
= 0; i
< func_desc
->cParams
; i
++)
7516 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7518 if (wParamFlags
& PARAMFLAG_FLCID
)
7520 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7522 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7526 VariantInit(pVarResult
);
7527 /* deref return value */
7528 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7531 VARIANT_ClearInd(prgpvarg
[i
]);
7533 else if (vargs_converted
< pDispParams
->cArgs
)
7535 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7536 if (wParamFlags
& PARAMFLAG_FOUT
)
7538 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7540 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7544 ERR("failed to convert param %d to vt %d\n", i
,
7545 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7550 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7551 func_desc
->cParamsOpt
< 0 &&
7552 i
== func_desc
->cParams
-1)
7554 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7557 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7560 ERR("SafeArrayGetUBound failed with %#lx.\n", hres
);
7563 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7566 ERR("SafeArrayAccessData failed with %#lx.\n", hres
);
7569 for (j
= 0; j
<= ubound
; j
++)
7570 VariantClear(&v
[j
]);
7571 hres
= SafeArrayUnaccessData(a
);
7574 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres
);
7578 VariantClear(&rgvarg
[i
]);
7581 else if (wParamFlags
& PARAMFLAG_FOPT
)
7583 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7584 VariantClear(&rgvarg
[i
]);
7587 VariantClear(&missing_arg
[i
]);
7590 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7592 WARN("invoked function failed with error %#lx.\n", V_ERROR(&varresult
));
7593 hres
= DISP_E_EXCEPTION
;
7596 IErrorInfo
*pErrorInfo
;
7597 pExcepInfo
->scode
= V_ERROR(&varresult
);
7598 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7600 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7601 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7602 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7603 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7605 IErrorInfo_Release(pErrorInfo
);
7609 if (V_VT(&varresult
) != VT_ERROR
)
7611 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7615 VariantClear(pVarResult
);
7616 *pVarResult
= varresult
;
7619 VariantClear(&varresult
);
7622 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7623 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7624 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7625 (pDispParams
->cArgs
!= 0))
7627 if (V_VT(pVarResult
) == VT_DISPATCH
)
7629 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7630 /* Note: not VariantClear; we still need the dispatch
7631 * pointer to be valid */
7632 VariantInit(pVarResult
);
7633 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7634 GetSystemDefaultLCID(), wFlags
,
7635 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7636 IDispatch_Release(pDispatch
);
7640 VariantClear(pVarResult
);
7641 hres
= DISP_E_NOTACOLLECTION
;
7649 case FUNC_DISPATCH
: {
7652 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7653 if (SUCCEEDED(hres
)) {
7654 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7655 hres
= IDispatch_Invoke(
7656 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7657 pVarResult
,pExcepInfo
,pArgErr
7660 FIXME("IDispatch::Invoke failed with %#lx. (Could be not a real error?)\n", hres
);
7661 IDispatch_Release(disp
);
7663 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7667 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7672 TRACE("-- %#lx\n", hres
);
7675 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7678 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7679 if(FAILED(hres
)) return hres
;
7681 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7682 dump_VARDESC(var_desc
);
7683 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7687 /* not found, look for it in inherited interfaces */
7688 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7689 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7690 if(This
->impltypes
) {
7691 /* recursive search */
7693 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7694 if(SUCCEEDED(hres
)){
7695 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7696 ITypeInfo_Release(pTInfo
);
7699 WARN("Could not search inherited interface!\n");
7702 WARN("did not find member id %ld, flags 0x%x!\n", memid
, wFlags
);
7703 return DISP_E_MEMBERNOTFOUND
;
7706 /* ITypeInfo::GetDocumentation
7708 * Retrieves the documentation string, the complete Help file name and path,
7709 * and the context ID for the Help topic for a specified type description.
7711 * (Can be tested by the Visual Basic Editor in Word for instance.)
7713 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7714 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7715 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7717 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7718 const TLBFuncDesc
*pFDesc
;
7719 const TLBVarDesc
*pVDesc
;
7720 TRACE("%p, %ld, %p, %p, %p, %p.\n",
7721 iface
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7722 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7724 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7726 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7728 *pdwHelpContext
=This
->dwHelpContext
;
7730 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7732 }else {/* for a member */
7733 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
7736 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7738 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7740 *pdwHelpContext
=pFDesc
->helpcontext
;
7742 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7745 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
7748 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7750 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7752 *pdwHelpContext
=pVDesc
->HelpContext
;
7754 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7759 if(This
->impltypes
&&
7760 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7761 /* recursive search */
7764 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7765 if(SUCCEEDED(result
)) {
7766 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7767 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7768 ITypeInfo_Release(pTInfo
);
7771 WARN("Could not search inherited interface!\n");
7774 WARN("member %ld not found\n", memid
);
7775 return TYPE_E_ELEMENTNOTFOUND
;
7778 /* ITypeInfo::GetDllEntry
7780 * Retrieves a description or specification of an entry point for a function
7783 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7784 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7787 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7788 const TLBFuncDesc
*pFDesc
;
7790 TRACE("%p, %#lx, %d, %p, %p, %p.\n", iface
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7792 if (pBstrDllName
) *pBstrDllName
= NULL
;
7793 if (pBstrName
) *pBstrName
= NULL
;
7794 if (pwOrdinal
) *pwOrdinal
= 0;
7796 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7797 return TYPE_E_BADMODULEKIND
;
7799 pFDesc
= TLB_get_funcdesc_by_memberid_invkind(This
, memid
, invKind
);
7800 if (!pFDesc
) return TYPE_E_ELEMENTNOTFOUND
;
7802 dump_TypeInfo(This
);
7803 if (TRACE_ON(ole
)) dump_TLBFuncDescOne(pFDesc
);
7805 if (pBstrDllName
) *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7807 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1))
7809 if (pBstrName
) *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7810 if (pwOrdinal
) *pwOrdinal
= -1;
7814 if (pBstrName
) *pBstrName
= NULL
;
7815 if (pwOrdinal
) *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7820 /* internal function to make the inherited interfaces' methods appear
7821 * part of the interface */
7822 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7823 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7825 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7828 TRACE("%p, %#lx.\n", iface
, *hRefType
);
7830 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7832 ITypeInfo
*pSubTypeInfo
;
7834 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7838 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7840 ITypeInfo_Release(pSubTypeInfo
);
7844 *hRefType
-= DISPATCH_HREF_OFFSET
;
7846 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7847 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7852 /* ITypeInfo::GetRefTypeInfo
7854 * If a type description references other type descriptions, it retrieves
7855 * the referenced type descriptions.
7857 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7860 ITypeInfo
**ppTInfo
)
7862 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7863 ITypeInfo
*type_info
= NULL
;
7864 HRESULT result
= E_FAIL
;
7865 TLBRefType
*ref_type
;
7869 return E_INVALIDARG
;
7871 if ((INT
)hRefType
< 0) {
7872 ITypeInfoImpl
*pTypeInfoImpl
;
7874 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7875 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7876 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7877 return TYPE_E_ELEMENTNOTFOUND
;
7879 /* when we meet a DUAL typeinfo, we must create the alternate
7882 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7884 *pTypeInfoImpl
= *This
;
7885 pTypeInfoImpl
->ref
= 0;
7886 list_init(&pTypeInfoImpl
->custdata_list
);
7888 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7889 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7891 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7893 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7894 /* the AddRef implicitly adds a reference to the parent typelib, which
7895 * stops the copied data from being destroyed until the new typeinfo's
7896 * refcount goes to zero, but we need to signal to the new instance to
7897 * not free its data structures when it is destroyed */
7898 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7899 ITypeInfo_AddRef(*ppTInfo
);
7901 TRACE("got dual interface %p\n", *ppTInfo
);
7905 if ((hRefType
& DISPATCH_HREF_MASK
) && (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7906 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &hRefType
, ppTInfo
);
7908 if(!(hRefType
& 0x1))
7910 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7912 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7915 type_info
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7916 ITypeInfo_AddRef(type_info
);
7924 ITypeLib
*pTLib
= NULL
;
7926 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7928 if(ref_type
->reference
== (hRefType
& (~0x3)))
7931 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7933 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
7937 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7939 TRACE("internal reference\n");
7940 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7942 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7943 TRACE("typeinfo in imported typelib that is already loaded\n");
7944 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7945 ITypeLib_AddRef(pTLib
);
7948 /* Search in cached typelibs */
7949 ITypeLibImpl
*entry
;
7951 EnterCriticalSection(&cache_section
);
7952 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
7955 && IsEqualIID(&entry
->guid
->guid
, TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
))
7956 && entry
->ver_major
== ref_type
->pImpTLInfo
->wVersionMajor
7957 && entry
->ver_minor
== ref_type
->pImpTLInfo
->wVersionMinor
7958 && entry
->set_lcid
== ref_type
->pImpTLInfo
->lcid
7959 && entry
->syskind
== This
->pTypeLib
->syskind
)
7961 TRACE("got cached %p\n", entry
);
7962 pTLib
= (ITypeLib
*)&entry
->ITypeLib2_iface
;
7963 ITypeLib_AddRef(pTLib
);
7968 LeaveCriticalSection(&cache_section
);
7974 /* Search on disk */
7975 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7976 ref_type
->pImpTLInfo
->wVersionMajor
,
7977 ref_type
->pImpTLInfo
->wVersionMinor
,
7978 This
->pTypeLib
->syskind
,
7979 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7981 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7983 result
= LoadTypeLib(libnam
, &pTLib
);
7984 SysFreeString(libnam
);
7987 if(SUCCEEDED(result
)) {
7988 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7989 ITypeLib_AddRef(pTLib
);
7993 if(SUCCEEDED(result
)) {
7994 if(ref_type
->index
== TLB_REF_USE_GUID
)
7995 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), &type_info
);
7997 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, &type_info
);
8000 ITypeLib_Release(pTLib
);
8003 WARN("(%p) failed hreftype %#lx.\n", iface
, hRefType
);
8008 if ((hRefType
& 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info
, -2, ppTInfo
)))
8009 ITypeInfo_Release(type_info
);
8010 else *ppTInfo
= type_info
;
8012 TRACE("%p, hreftype %#lx, loaded %s (%p)\n", iface
, hRefType
,
8013 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
8017 /* ITypeInfo::AddressOfMember
8019 * Retrieves the addresses of static functions or variables, such as those
8022 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
8023 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
8030 TRACE("%p, %lx, %#x, %p.\n", iface
, memid
, invKind
, ppv
);
8032 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
8036 module
= LoadLibraryW(dll
);
8039 ERR("couldn't load %s\n", debugstr_w(dll
));
8041 SysFreeString(entry
);
8042 return STG_E_FILENOTFOUND
;
8044 /* FIXME: store library somewhere where we can free it */
8049 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
8050 entryA
= heap_alloc(len
);
8051 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
8053 *ppv
= GetProcAddress(module
, entryA
);
8055 ERR("function not found %s\n", debugstr_a(entryA
));
8061 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
8063 ERR("function not found %d\n", ordinal
);
8067 SysFreeString(entry
);
8070 return TYPE_E_DLLFUNCTIONNOTFOUND
;
8075 /* ITypeInfo::CreateInstance
8077 * Creates a new instance of a type that describes a component object class
8080 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
8081 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
8083 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8087 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
8093 WARN("Not able to aggregate\n");
8094 return CLASS_E_NOAGGREGATION
;
8097 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
8098 if(FAILED(hr
)) return hr
;
8100 if(pTA
->typekind
!= TKIND_COCLASS
)
8102 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
8108 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
8111 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
8112 TRACE("GetActiveObject rets %#lx.\n", hr
);
8115 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
8116 IUnknown_Release(pUnk
);
8121 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
8122 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8126 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8130 /* ITypeInfo::GetMops
8132 * Retrieves marshalling information.
8134 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
, BSTR
*pBstrMops
)
8136 FIXME("%p, %ld stub!\n", iface
, memid
);
8141 /* ITypeInfo::GetContainingTypeLib
8143 * Retrieves the containing type library and the index of the type description
8144 * within that type library.
8146 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8147 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8149 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8151 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8153 *pIndex
=This
->index
;
8154 TRACE("returning pIndex=%d\n", *pIndex
);
8158 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8159 ITypeLib_AddRef(*ppTLib
);
8160 TRACE("returning ppTLib=%p\n", *ppTLib
);
8166 /* ITypeInfo::ReleaseTypeAttr
8168 * Releases a TYPEATTR previously returned by Get
8171 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8172 TYPEATTR
* pTypeAttr
)
8174 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8175 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8176 heap_free(pTypeAttr
);
8179 /* ITypeInfo::ReleaseFuncDesc
8181 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8183 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8185 FUNCDESC
*pFuncDesc
)
8187 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8190 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8192 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8193 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8194 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8196 SysFreeString((BSTR
)pFuncDesc
);
8199 /* ITypeInfo::ReleaseVarDesc
8201 * Releases a VARDESC previously returned by GetVarDesc.
8203 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8206 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8207 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8209 TLB_FreeVarDesc(pVarDesc
);
8212 /* ITypeInfo2::GetTypeKind
8214 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8217 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8218 TYPEKIND
*pTypeKind
)
8220 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8221 *pTypeKind
= This
->typeattr
.typekind
;
8222 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8226 /* ITypeInfo2::GetTypeFlags
8228 * Returns the type flags without any allocations. This returns a DWORD type
8229 * flag, which expands the type flags without growing the TYPEATTR (type
8233 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8235 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8236 TRACE("%p, %p.\n", iface
, pTypeFlags
);
8237 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8241 /* ITypeInfo2::GetFuncIndexOfMemId
8242 * Binds to a specific member based on a known DISPID, where the member name
8243 * is not known (for example, when binding to a default member).
8246 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8247 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8249 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8253 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8254 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8255 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8258 if(fdc
< This
->typeattr
.cFuncs
) {
8262 result
= TYPE_E_ELEMENTNOTFOUND
;
8264 TRACE("%p, %#lx, %#x, hr %#lx.\n", iface
, memid
, invKind
, result
);
8268 /* TypeInfo2::GetVarIndexOfMemId
8270 * Binds to a specific member based on a known DISPID, where the member name
8271 * is not known (for example, when binding to a default member).
8274 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8275 MEMBERID memid
, UINT
*pVarIndex
)
8277 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8278 TLBVarDesc
*pVarInfo
;
8280 TRACE("%p, %ld, %p.\n", iface
, memid
, pVarIndex
);
8282 pVarInfo
= TLB_get_vardesc_by_memberid(This
, memid
);
8284 return TYPE_E_ELEMENTNOTFOUND
;
8286 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8291 /* ITypeInfo2::GetCustData
8293 * Gets the custom data
8295 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8300 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8301 TLBCustData
*pCData
;
8303 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8305 if(!guid
|| !pVarVal
)
8306 return E_INVALIDARG
;
8308 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8310 VariantInit( pVarVal
);
8312 VariantCopy( pVarVal
, &pCData
->data
);
8314 VariantClear( pVarVal
);
8318 /* ITypeInfo2::GetFuncCustData
8320 * Gets the custom data
8322 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8328 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8329 const TLBFuncDesc
*desc
;
8334 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8336 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &desc
, &hrefoffset
);
8339 WARN("description for function %d not found\n", index
);
8343 VariantInit(pVarVal
);
8344 data
= TLB_get_custdata_by_guid(&desc
->custdata_list
, guid
);
8345 return data
? VariantCopy(pVarVal
, &data
->data
) : S_OK
;
8348 /* ITypeInfo2::GetParamCustData
8350 * Gets the custom data
8352 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8359 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8360 const TLBFuncDesc
*pFDesc
;
8361 TLBCustData
*pCData
;
8365 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8366 debugstr_guid(guid
), pVarVal
);
8368 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8372 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8373 return TYPE_E_ELEMENTNOTFOUND
;
8375 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8377 return TYPE_E_ELEMENTNOTFOUND
;
8379 VariantInit(pVarVal
);
8380 VariantCopy(pVarVal
, &pCData
->data
);
8385 /* ITypeInfo2::GetVarCustData
8387 * Gets the custom data
8389 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8395 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8396 TLBCustData
*pCData
;
8397 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8399 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8401 if(index
>= This
->typeattr
.cVars
)
8402 return TYPE_E_ELEMENTNOTFOUND
;
8404 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8406 return TYPE_E_ELEMENTNOTFOUND
;
8408 VariantInit(pVarVal
);
8409 VariantCopy(pVarVal
, &pCData
->data
);
8414 /* ITypeInfo2::GetImplCustData
8416 * Gets the custom data
8418 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8424 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8425 TLBCustData
*pCData
;
8426 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8428 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8430 if(index
>= This
->typeattr
.cImplTypes
)
8431 return TYPE_E_ELEMENTNOTFOUND
;
8433 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8435 return TYPE_E_ELEMENTNOTFOUND
;
8437 VariantInit(pVarVal
);
8438 VariantCopy(pVarVal
, &pCData
->data
);
8443 /* ITypeInfo2::GetDocumentation2
8445 * Retrieves the documentation string, the complete Help file name and path,
8446 * the localization context to use, and the context ID for the library Help
8447 * topic in the Help file.
8450 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8454 BSTR
*pbstrHelpString
,
8455 DWORD
*pdwHelpStringContext
,
8456 BSTR
*pbstrHelpStringDll
)
8458 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8459 const TLBFuncDesc
*pFDesc
;
8460 const TLBVarDesc
*pVDesc
;
8461 TRACE("%p, %ld, %#lx, %p, %p, %p.\n",
8462 iface
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8463 pbstrHelpStringDll
);
8464 /* the help string should be obtained from the helpstringdll,
8465 * using the _DLLGetDocumentation function, based on the supplied
8466 * lcid. Nice to do sometime...
8468 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8470 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8471 if(pdwHelpStringContext
)
8472 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8473 if(pbstrHelpStringDll
)
8474 *pbstrHelpStringDll
=
8475 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8477 }else {/* for a member */
8478 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
8481 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8482 if(pdwHelpStringContext
)
8483 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8484 if(pbstrHelpStringDll
)
8485 *pbstrHelpStringDll
=
8486 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8489 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
8492 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8493 if(pdwHelpStringContext
)
8494 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8495 if(pbstrHelpStringDll
)
8496 *pbstrHelpStringDll
=
8497 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8501 return TYPE_E_ELEMENTNOTFOUND
;
8504 /* ITypeInfo2::GetAllCustData
8506 * Gets all custom data items for the Type info.
8509 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8511 CUSTDATA
*pCustData
)
8513 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8515 TRACE("%p %p\n", This
, pCustData
);
8517 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8520 /* ITypeInfo2::GetAllFuncCustData
8522 * Gets all custom data items for the specified Function
8525 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8528 CUSTDATA
*pCustData
)
8530 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8531 const TLBFuncDesc
*pFDesc
;
8535 TRACE("%p %u %p\n", This
, index
, pCustData
);
8537 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &pFDesc
, &hrefoffset
);
8541 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8544 /* ITypeInfo2::GetAllParamCustData
8546 * Gets all custom data items for the Functions
8549 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8550 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8552 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8553 const TLBFuncDesc
*pFDesc
;
8557 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8559 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8563 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8564 return TYPE_E_ELEMENTNOTFOUND
;
8566 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8569 /* ITypeInfo2::GetAllVarCustData
8571 * Gets all custom data items for the specified Variable
8574 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8575 UINT index
, CUSTDATA
*pCustData
)
8577 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8578 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8580 TRACE("%p %u %p\n", This
, index
, pCustData
);
8582 if(index
>= This
->typeattr
.cVars
)
8583 return TYPE_E_ELEMENTNOTFOUND
;
8585 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8588 /* ITypeInfo2::GetAllImplCustData
8590 * Gets all custom data items for the specified implementation type
8593 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8596 CUSTDATA
*pCustData
)
8598 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8599 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8601 TRACE("%p %u %p\n", This
, index
, pCustData
);
8603 if(index
>= This
->typeattr
.cImplTypes
)
8604 return TYPE_E_ELEMENTNOTFOUND
;
8606 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8609 static const ITypeInfo2Vtbl tinfvt
=
8612 ITypeInfo_fnQueryInterface
,
8614 ITypeInfo_fnRelease
,
8616 ITypeInfo_fnGetTypeAttr
,
8617 ITypeInfo_fnGetTypeComp
,
8618 ITypeInfo_fnGetFuncDesc
,
8619 ITypeInfo_fnGetVarDesc
,
8620 ITypeInfo_fnGetNames
,
8621 ITypeInfo_fnGetRefTypeOfImplType
,
8622 ITypeInfo_fnGetImplTypeFlags
,
8623 ITypeInfo_fnGetIDsOfNames
,
8625 ITypeInfo_fnGetDocumentation
,
8626 ITypeInfo_fnGetDllEntry
,
8627 ITypeInfo_fnGetRefTypeInfo
,
8628 ITypeInfo_fnAddressOfMember
,
8629 ITypeInfo_fnCreateInstance
,
8630 ITypeInfo_fnGetMops
,
8631 ITypeInfo_fnGetContainingTypeLib
,
8632 ITypeInfo_fnReleaseTypeAttr
,
8633 ITypeInfo_fnReleaseFuncDesc
,
8634 ITypeInfo_fnReleaseVarDesc
,
8636 ITypeInfo2_fnGetTypeKind
,
8637 ITypeInfo2_fnGetTypeFlags
,
8638 ITypeInfo2_fnGetFuncIndexOfMemId
,
8639 ITypeInfo2_fnGetVarIndexOfMemId
,
8640 ITypeInfo2_fnGetCustData
,
8641 ITypeInfo2_fnGetFuncCustData
,
8642 ITypeInfo2_fnGetParamCustData
,
8643 ITypeInfo2_fnGetVarCustData
,
8644 ITypeInfo2_fnGetImplTypeCustData
,
8645 ITypeInfo2_fnGetDocumentation2
,
8646 ITypeInfo2_fnGetAllCustData
,
8647 ITypeInfo2_fnGetAllFuncCustData
,
8648 ITypeInfo2_fnGetAllParamCustData
,
8649 ITypeInfo2_fnGetAllVarCustData
,
8650 ITypeInfo2_fnGetAllImplTypeCustData
,
8653 /******************************************************************************
8654 * CreateDispTypeInfo [OLEAUT32.31]
8656 * Build type information for an object so it can be called through an
8657 * IDispatch interface.
8660 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8661 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8664 * This call allows an objects methods to be accessed through IDispatch, by
8665 * building an ITypeInfo object that IDispatch can use to call through.
8667 HRESULT WINAPI
CreateDispTypeInfo(
8668 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8669 LCID lcid
, /* [I] Locale Id */
8670 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8672 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8673 ITypeLibImpl
*pTypeLibImpl
;
8674 unsigned int param
, func
;
8675 TLBFuncDesc
*pFuncDesc
;
8679 pTypeLibImpl
= TypeLibImpl_Constructor();
8680 if (!pTypeLibImpl
) return E_FAIL
;
8682 pTypeLibImpl
->TypeInfoCount
= 2;
8683 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8685 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8686 pTIIface
->pTypeLib
= pTypeLibImpl
;
8687 pTIIface
->index
= 0;
8688 pTIIface
->Name
= NULL
;
8689 pTIIface
->dwHelpContext
= -1;
8690 pTIIface
->guid
= NULL
;
8691 pTIIface
->typeattr
.lcid
= lcid
;
8692 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8693 pTIIface
->typeattr
.wMajorVerNum
= 0;
8694 pTIIface
->typeattr
.wMinorVerNum
= 0;
8695 pTIIface
->typeattr
.cbAlignment
= 2;
8696 pTIIface
->typeattr
.cbSizeInstance
= -1;
8697 pTIIface
->typeattr
.cbSizeVft
= -1;
8698 pTIIface
->typeattr
.cFuncs
= 0;
8699 pTIIface
->typeattr
.cImplTypes
= 0;
8700 pTIIface
->typeattr
.cVars
= 0;
8701 pTIIface
->typeattr
.wTypeFlags
= 0;
8702 pTIIface
->hreftype
= 0;
8704 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8705 pFuncDesc
= pTIIface
->funcdescs
;
8706 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8707 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8708 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8709 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8710 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8711 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8712 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8713 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8714 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8715 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8716 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8717 pFuncDesc
->funcdesc
.cScodes
= 0;
8718 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8719 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8720 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8721 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8722 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8723 md
->cArgs
* sizeof(ELEMDESC
));
8724 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8725 for(param
= 0; param
< md
->cArgs
; param
++) {
8726 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8727 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8729 pFuncDesc
->helpcontext
= 0;
8730 pFuncDesc
->HelpStringContext
= 0;
8731 pFuncDesc
->HelpString
= NULL
;
8732 pFuncDesc
->Entry
= NULL
;
8733 list_init(&pFuncDesc
->custdata_list
);
8734 pTIIface
->typeattr
.cFuncs
++;
8738 dump_TypeInfo(pTIIface
);
8740 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8741 pTIClass
->pTypeLib
= pTypeLibImpl
;
8742 pTIClass
->index
= 1;
8743 pTIClass
->Name
= NULL
;
8744 pTIClass
->dwHelpContext
= -1;
8745 pTIClass
->guid
= NULL
;
8746 pTIClass
->typeattr
.lcid
= lcid
;
8747 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8748 pTIClass
->typeattr
.wMajorVerNum
= 0;
8749 pTIClass
->typeattr
.wMinorVerNum
= 0;
8750 pTIClass
->typeattr
.cbAlignment
= 2;
8751 pTIClass
->typeattr
.cbSizeInstance
= -1;
8752 pTIClass
->typeattr
.cbSizeVft
= -1;
8753 pTIClass
->typeattr
.cFuncs
= 0;
8754 pTIClass
->typeattr
.cImplTypes
= 1;
8755 pTIClass
->typeattr
.cVars
= 0;
8756 pTIClass
->typeattr
.wTypeFlags
= 0;
8757 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8759 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8761 ref
= heap_alloc_zero(sizeof(*ref
));
8762 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8763 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8765 dump_TypeInfo(pTIClass
);
8767 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8769 ITypeInfo_AddRef(*pptinfo
);
8770 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8776 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8778 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8780 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8783 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8785 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8787 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8790 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8792 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8794 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8797 static HRESULT WINAPI
ITypeComp_fnBind(
8802 ITypeInfo
** ppTInfo
,
8803 DESCKIND
* pDescKind
,
8806 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8807 const TLBFuncDesc
*pFDesc
;
8808 const TLBVarDesc
*pVDesc
;
8809 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8812 TRACE("%p, %s, %#lx, 0x%x, %p, %p, %p.\n", iface
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8814 *pDescKind
= DESCKIND_NONE
;
8815 pBindPtr
->lpfuncdesc
= NULL
;
8818 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8819 pFDesc
= &This
->funcdescs
[fdc
];
8820 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8821 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8824 /* name found, but wrong flags */
8825 hr
= TYPE_E_TYPEMISMATCH
;
8829 if (fdc
< This
->typeattr
.cFuncs
)
8831 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8833 &pBindPtr
->lpfuncdesc
,
8834 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8837 *pDescKind
= DESCKIND_FUNCDESC
;
8838 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8839 ITypeInfo_AddRef(*ppTInfo
);
8842 pVDesc
= TLB_get_vardesc_by_name(This
, szName
);
8844 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8847 *pDescKind
= DESCKIND_VARDESC
;
8848 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8849 ITypeInfo_AddRef(*ppTInfo
);
8854 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8855 /* recursive search */
8859 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8862 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8863 ITypeInfo_Release(pTInfo
);
8867 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8868 ITypeComp_Release(pTComp
);
8869 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8870 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8872 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8873 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8874 SysFreeString((BSTR
)tmp
);
8878 WARN("Could not search inherited interface!\n");
8880 if (hr
== DISP_E_MEMBERNOTFOUND
)
8882 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8886 static HRESULT WINAPI
ITypeComp_fnBindType(
8890 ITypeInfo
** ppTInfo
,
8891 ITypeComp
** ppTComp
)
8893 TRACE("%s, %#lx, %p, %p.\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8895 /* strange behaviour (does nothing) but like the
8898 if (!ppTInfo
|| !ppTComp
)
8907 static const ITypeCompVtbl tcompvt
=
8910 ITypeComp_fnQueryInterface
,
8912 ITypeComp_fnRelease
,
8915 ITypeComp_fnBindType
8918 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8919 ICreateTypeLib2
** ppctlib
)
8924 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8926 if (!szFile
) return E_INVALIDARG
;
8928 This
= TypeLibImpl_Constructor();
8930 return E_OUTOFMEMORY
;
8932 This
->lcid
= GetSystemDefaultLCID();
8933 This
->syskind
= syskind
;
8934 This
->ptr_size
= get_ptr_size(syskind
);
8936 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8938 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8939 return E_OUTOFMEMORY
;
8941 lstrcpyW(This
->path
, szFile
);
8943 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8944 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8948 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8949 REFIID riid
, void **object
)
8951 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8953 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8956 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8958 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8960 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8963 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8965 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8967 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8970 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8971 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8973 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8974 ITypeInfoImpl
*info
;
8977 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8979 if (!ctinfo
|| !name
)
8980 return E_INVALIDARG
;
8982 info
= TLB_get_typeinfo_by_name(This
, name
);
8984 return TYPE_E_NAMECONFLICT
;
8986 if (This
->typeinfos
)
8987 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8988 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8990 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8992 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8994 info
->pTypeLib
= This
;
8995 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8996 info
->index
= This
->TypeInfoCount
;
8997 info
->typeattr
.typekind
= kind
;
8998 info
->typeattr
.cbAlignment
= 4;
9000 switch (info
->typeattr
.typekind
) {
9002 case TKIND_INTERFACE
:
9003 case TKIND_DISPATCH
:
9005 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
9009 info
->typeattr
.cbSizeInstance
= 0;
9012 info
->typeattr
.cbSizeInstance
= 2;
9015 info
->typeattr
.cbSizeInstance
= -0x75;
9018 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
9019 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
9023 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
9024 &IID_ICreateTypeInfo
, (void **)ctinfo
);
9026 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
9030 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
9032 ++This
->TypeInfoCount
;
9037 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
9040 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9042 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
9045 return E_INVALIDARG
;
9047 This
->Name
= TLB_append_str(&This
->name_list
, name
);
9052 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
9053 WORD majorVerNum
, WORD minorVerNum
)
9055 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9057 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
9059 This
->ver_major
= majorVerNum
;
9060 This
->ver_minor
= minorVerNum
;
9065 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
9068 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9070 TRACE("%p %s\n", This
, debugstr_guid(guid
));
9072 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
9077 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
9080 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9082 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
9085 return E_INVALIDARG
;
9087 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
9092 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
9093 LPOLESTR helpFileName
)
9095 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9097 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
9100 return E_INVALIDARG
;
9102 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
9107 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
9110 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9112 TRACE("%p, %ld.\n", iface
, helpContext
);
9114 This
->dwHelpContext
= helpContext
;
9119 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
9122 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9124 TRACE("%p, %#lx.\n", iface
, lcid
);
9126 This
->set_lcid
= lcid
;
9131 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9134 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9136 TRACE("%p %x\n", This
, libFlags
);
9138 This
->libflags
= libFlags
;
9143 typedef struct tagWMSFT_SegContents
{
9146 } WMSFT_SegContents
;
9148 typedef struct tagWMSFT_TLBFile
{
9150 WMSFT_SegContents typeinfo_seg
;
9151 WMSFT_SegContents impfile_seg
;
9152 WMSFT_SegContents impinfo_seg
;
9153 WMSFT_SegContents ref_seg
;
9154 WMSFT_SegContents guidhash_seg
;
9155 WMSFT_SegContents guid_seg
;
9156 WMSFT_SegContents namehash_seg
;
9157 WMSFT_SegContents name_seg
;
9158 WMSFT_SegContents string_seg
;
9159 WMSFT_SegContents typdesc_seg
;
9160 WMSFT_SegContents arraydesc_seg
;
9161 WMSFT_SegContents custdata_seg
;
9162 WMSFT_SegContents cdguids_seg
;
9164 WMSFT_SegContents aux_seg
;
9167 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9168 WMSFT_TLBFile
*file
)
9174 file
->string_seg
.len
= 0;
9175 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9178 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9180 return E_UNEXPECTED
;
9182 size
+= sizeof(INT16
);
9184 size
= (size
+ 4) & ~0x3;
9188 file
->string_seg
.len
+= size
;
9190 /* temporarily use str->offset to store the length of the aligned,
9191 * converted string */
9195 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
9198 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9201 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9202 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9204 heap_free(file
->string_seg
.data
);
9205 return E_UNEXPECTED
;
9208 *((INT16
*)data
) = size
;
9210 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9214 str
->offset
= last_offs
;
9221 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9222 WMSFT_TLBFile
*file
)
9227 MSFT_NameIntro
*last_intro
= NULL
;
9229 file
->header
.nametablecount
= 0;
9230 file
->header
.nametablechars
= 0;
9232 file
->name_seg
.len
= 0;
9233 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9236 size
= lstrlenW(str
->str
);
9237 file
->header
.nametablechars
+= size
;
9238 file
->header
.nametablecount
++;
9240 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9242 return E_UNEXPECTED
;
9244 size
+= sizeof(MSFT_NameIntro
);
9246 size
= (size
+ 4) & ~0x3;
9250 file
->name_seg
.len
+= size
;
9252 /* temporarily use str->offset to store the length of the aligned,
9253 * converted string */
9257 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9258 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
9261 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9263 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9265 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9266 data
+ sizeof(MSFT_NameIntro
),
9267 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9269 heap_free(file
->name_seg
.data
);
9270 return E_UNEXPECTED
;
9272 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9274 intro
->hreftype
= -1; /* TODO? */
9275 intro
->namelen
= size
& 0xFF;
9276 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9277 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9278 intro
->namelen
|= hash
<< 16;
9279 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9280 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9282 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9283 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9285 /* update str->offset to actual value to use in other
9286 * compilation functions that require positions within
9287 * the string table */
9291 str
->offset
= last_offs
;
9296 last_intro
->hreftype
= 0; /* last one is 0? */
9301 static inline int hash_guid(GUID
*guid
)
9305 for (i
= 0; i
< 8; i
++)
9306 hash
^= ((const short *)guid
)[i
];
9311 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9314 MSFT_GuidEntry
*entry
;
9316 int hash_key
, *guidhashtab
;
9318 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9319 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9321 entry
= file
->guid_seg
.data
;
9323 guidhashtab
= file
->guidhash_seg
.data
;
9324 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9325 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9326 entry
->hreftype
= guid
->hreftype
;
9328 hash_key
= hash_guid(&guid
->guid
);
9329 entry
->next_hash
= guidhashtab
[hash_key
];
9330 guidhashtab
[hash_key
] = offs
;
9332 guid
->offset
= offs
;
9333 offs
+= sizeof(MSFT_GuidEntry
);
9340 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9343 VARTYPE arg_type
= V_VT(value
);
9346 DWORD ret
= file
->custdata_seg
.len
;
9348 if(arg_type
== VT_INT
)
9350 if(arg_type
== VT_UINT
)
9354 if(V_VT(value
) != arg_type
) {
9355 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9357 ERR("VariantChangeType failed: %#lx.\n", hres
);
9362 /* Check if default value can be stored in-place */
9367 if(V_UI4(&v
) > 0x3ffffff)
9380 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9383 /* have to allocate space in custdata_seg */
9392 /* Construct the data to be allocated */
9395 if(file
->custdata_seg
.data
){
9396 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9397 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9398 file
->custdata_seg
.len
+= sizeof(int) * 2;
9400 file
->custdata_seg
.len
= sizeof(int) * 2;
9401 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9404 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9405 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9407 /* TODO: Check if the encoded data is already present in custdata_seg */
9413 int mb_len
= WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), NULL
, 0, NULL
, NULL
);
9414 int i
, len
= (6 + mb_len
+ 3) & ~0x3;
9417 if(file
->custdata_seg
.data
){
9418 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9419 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9420 file
->custdata_seg
.len
+= len
;
9422 file
->custdata_seg
.len
= len
;
9423 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9426 *((unsigned short *)data
) = V_VT(value
);
9427 *((unsigned int *)(data
+2)) = mb_len
;
9428 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], mb_len
, NULL
, NULL
);
9429 for (i
= 6 + mb_len
; i
< len
; i
++)
9432 /* TODO: Check if the encoded data is already present in custdata_seg */
9437 FIXME("Argument type not yet handled\n");
9442 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9444 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9446 DWORD offs
= file
->arraydesc_seg
.len
;
9450 /* TODO: we should check for duplicates, but that's harder because each
9451 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9452 * at the library-level) */
9454 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9455 if(!file
->arraydesc_seg
.data
)
9456 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9458 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9459 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9461 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9462 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9463 for(i
= 0; i
< desc
->cDims
; ++i
){
9464 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9465 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9471 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9477 VARTYPE vt
, subtype
;
9488 vt
= desc
->vt
& VT_TYPEMASK
;
9490 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9492 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9493 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9495 *out_size
+= 2 * sizeof(DWORD
);
9496 }else if(vt
== VT_CARRAY
){
9497 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9498 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9500 }else if(vt
== VT_USERDEFINED
){
9501 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9502 encoded
[1] = desc
->u
.hreftype
;
9503 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9505 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9523 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9526 data
= file
->typdesc_seg
.data
;
9527 while(offs
< file
->typdesc_seg
.len
){
9528 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9530 offs
+= sizeof(encoded
);
9533 file
->typdesc_seg
.len
+= sizeof(encoded
);
9534 if(!file
->typdesc_seg
.data
)
9535 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9537 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9539 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9544 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9546 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9547 DWORD ret
= cdguids_seg
->len
, offs
;
9548 MSFT_CDGuid
*cdguid
;
9551 if(list_empty(custdata_list
))
9554 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9555 if(!cdguids_seg
->data
){
9556 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9558 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9559 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9562 offs
= ret
+ sizeof(MSFT_CDGuid
);
9563 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9564 cdguid
->GuidOffset
= cd
->guid
->offset
;
9565 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9566 cdguid
->next
= offs
;
9567 offs
+= sizeof(MSFT_CDGuid
);
9577 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9578 WMSFT_TLBFile
*file
)
9580 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9581 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9582 MSFT_VarRecord
*varrecord
;
9583 MSFT_FuncRecord
*funcrecord
;
9585 DWORD
*name
, *offsets
, offs
;
9587 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9588 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9590 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9592 /* optional fields */
9593 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9594 if(!list_empty(&desc
->custdata_list
))
9595 recorded_size
+= 7 * sizeof(INT
);
9596 else if(desc
->HelpStringContext
!= 0)
9597 recorded_size
+= 6 * sizeof(INT
);
9599 else if(desc
->Entry
)
9600 recorded_size
+= 3 * sizeof(INT
);
9601 else if(desc
->HelpString
)
9602 recorded_size
+= 2 * sizeof(INT
);
9603 else if(desc
->helpcontext
)
9604 recorded_size
+= sizeof(INT
);
9606 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9608 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9609 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9610 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9615 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9618 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9619 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9621 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9623 /* optional fields */
9624 if(desc
->HelpStringContext
!= 0)
9625 recorded_size
+= 5 * sizeof(INT
);
9626 else if(!list_empty(&desc
->custdata_list
))
9627 recorded_size
+= 4 * sizeof(INT
);
9629 else if(desc
->HelpString
)
9630 recorded_size
+= 2 * sizeof(INT
);
9631 else if(desc
->HelpContext
!= 0)
9632 recorded_size
+= sizeof(INT
);
9634 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9637 if(!recorded_size
&& !extra_size
)
9640 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9642 aux_seg
->len
+= recorded_size
+ extra_size
;
9644 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9647 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9649 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9651 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9653 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9656 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9657 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9658 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9659 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9661 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9662 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9663 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9664 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9667 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9672 * ^has_param_defaults
9673 * ^oEntry_is_intresource
9675 funcrecord
->FKCCIC
=
9676 desc
->funcdesc
.funckind
|
9677 (desc
->funcdesc
.invkind
<< 3) |
9678 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9679 (desc
->funcdesc
.callconv
<< 8);
9681 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9682 funcrecord
->FKCCIC
|= 0x2000;
9684 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9685 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9686 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9687 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9690 if(paramdefault_size
> 0)
9691 funcrecord
->FKCCIC
|= 0x1000;
9693 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9694 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9696 /* optional fields */
9698 if(!list_empty(&desc
->custdata_list
)){
9699 size
+= 7 * sizeof(INT
);
9700 funcrecord
->HelpContext
= desc
->helpcontext
;
9701 if(desc
->HelpString
)
9702 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9704 funcrecord
->oHelpString
= -1;
9706 funcrecord
->oEntry
= -1;
9707 else if(IS_INTRESOURCE(desc
->Entry
))
9708 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9710 funcrecord
->oEntry
= desc
->Entry
->offset
;
9711 funcrecord
->res9
= -1;
9712 funcrecord
->resA
= -1;
9713 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9714 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9715 }else if(desc
->HelpStringContext
!= 0){
9716 size
+= 6 * sizeof(INT
);
9717 funcrecord
->HelpContext
= desc
->helpcontext
;
9718 if(desc
->HelpString
)
9719 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9721 funcrecord
->oHelpString
= -1;
9723 funcrecord
->oEntry
= -1;
9724 else if(IS_INTRESOURCE(desc
->Entry
))
9725 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9727 funcrecord
->oEntry
= desc
->Entry
->offset
;
9728 funcrecord
->res9
= -1;
9729 funcrecord
->resA
= -1;
9730 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9731 }else if(desc
->Entry
){
9732 size
+= 3 * sizeof(INT
);
9733 funcrecord
->HelpContext
= desc
->helpcontext
;
9734 if(desc
->HelpString
)
9735 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9737 funcrecord
->oHelpString
= -1;
9739 funcrecord
->oEntry
= -1;
9740 else if(IS_INTRESOURCE(desc
->Entry
))
9741 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9743 funcrecord
->oEntry
= desc
->Entry
->offset
;
9744 }else if(desc
->HelpString
){
9745 size
+= 2 * sizeof(INT
);
9746 funcrecord
->HelpContext
= desc
->helpcontext
;
9747 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9748 }else if(desc
->helpcontext
){
9749 size
+= sizeof(INT
);
9750 funcrecord
->HelpContext
= desc
->helpcontext
;
9753 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9754 size
+= paramdefault_size
;
9756 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9757 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9759 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9760 if(desc
->pParamDesc
[j
].Name
)
9761 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9764 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9766 if(paramdefault_size
){
9767 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9768 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9769 else if(paramdefault_size
)
9774 size
+= sizeof(MSFT_ParameterInfo
);
9777 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9783 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9786 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9787 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9788 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9789 DWORD size
= 5 * sizeof(INT
);
9791 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9792 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9793 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9794 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9796 if(desc
->vardesc
.varkind
== VAR_CONST
){
9797 varrecord
->vardescsize
+= sizeof(VARIANT
);
9798 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9800 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9803 if(desc
->HelpStringContext
!= 0){
9804 size
+= 5 * sizeof(INT
);
9805 varrecord
->HelpContext
= desc
->HelpContext
;
9806 if(desc
->HelpString
)
9807 varrecord
->HelpString
= desc
->HelpString
->offset
;
9809 varrecord
->HelpString
= -1;
9810 varrecord
->res9
= -1;
9811 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9812 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9813 }else if(!list_empty(&desc
->custdata_list
)){
9814 size
+= 4 * sizeof(INT
);
9815 varrecord
->HelpContext
= desc
->HelpContext
;
9816 if(desc
->HelpString
)
9817 varrecord
->HelpString
= desc
->HelpString
->offset
;
9819 varrecord
->HelpString
= -1;
9820 varrecord
->res9
= -1;
9821 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9822 }else if(desc
->HelpString
){
9823 size
+= 2 * sizeof(INT
);
9824 varrecord
->HelpContext
= desc
->HelpContext
;
9825 if(desc
->HelpString
)
9826 varrecord
->HelpString
= desc
->HelpString
->offset
;
9828 varrecord
->HelpString
= -1;
9829 }else if(desc
->HelpContext
!= 0){
9830 size
+= sizeof(INT
);
9831 varrecord
->HelpContext
= desc
->HelpContext
;
9834 varrecord
->Info
= size
| (i
<< 16);
9840 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9843 memid
= (MEMBERID
*)varrecord
;
9844 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9845 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9846 *memid
= desc
->funcdesc
.memid
;
9849 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9850 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9851 *memid
= desc
->vardesc
.memid
;
9855 name
= (DWORD
*)memid
;
9856 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9857 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9859 *name
= desc
->Name
->offset
;
9864 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9865 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9867 *name
= desc
->Name
->offset
;
9876 typedef struct tagWMSFT_RefChunk
{
9883 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9885 DWORD offs
= file
->ref_seg
.len
, i
;
9886 WMSFT_RefChunk
*chunk
;
9888 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9889 if(!file
->ref_seg
.data
)
9890 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9892 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9894 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9896 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9897 chunk
->href
= info
->impltypes
[i
].hRef
;
9898 chunk
->res04
= info
->impltypes
[i
].implflags
;
9900 if(i
< info
->typeattr
.cImplTypes
- 1)
9901 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9910 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9914 size
= sizeof(MSFT_TypeInfoBase
);
9917 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9918 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9919 base
->typekind
= TKIND_DISPATCH
;
9921 base
->typekind
= info
->typeattr
.typekind
;
9922 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9923 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
9924 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9929 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
9935 base
->posguid
= info
->guid
->offset
;
9938 base
->flags
= info
->typeattr
.wTypeFlags
;
9940 base
->NameOffset
= info
->Name
->offset
;
9942 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9943 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9945 base
->NameOffset
= -1;
9947 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
9949 base
->docstringoffs
= info
->DocString
->offset
;
9951 base
->docstringoffs
= -1;
9952 base
->helpstringcontext
= info
->dwHelpStringContext
;
9953 base
->helpcontext
= info
->dwHelpContext
;
9954 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9955 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
9956 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
9957 base
->size
= info
->typeattr
.cbSizeInstance
;
9958 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
9959 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9960 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
9961 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9962 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
9964 base
->datatype1
= info
->DllName
->offset
;
9966 base
->datatype1
= -1;
9968 if(info
->typeattr
.cImplTypes
> 0)
9969 base
->datatype1
= info
->impltypes
[0].hRef
;
9971 base
->datatype1
= -1;
9973 base
->datatype2
= index
; /* FIXME: i think there's more here */
9981 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9985 file
->typeinfo_seg
.len
= 0;
9986 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9987 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9988 *junk
= file
->typeinfo_seg
.len
;
9990 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9993 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9994 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9996 file
->aux_seg
.len
= 0;
9997 file
->aux_seg
.data
= NULL
;
9999 file
->typeinfo_seg
.len
= 0;
10000 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10001 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
10002 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
10003 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
10007 typedef struct tagWMSFT_ImpFile
{
10013 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10016 WMSFT_ImpFile
*impfile
;
10018 DWORD last_offs
= 0;
10020 file
->impfile_seg
.len
= 0;
10021 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10025 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10029 path
= implib
->name
;
10030 size
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
), NULL
, 0, NULL
, NULL
);
10032 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10035 size
+= sizeof(INT16
);
10037 size
= (size
+ 4) & ~0x3;
10041 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
10044 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
10046 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10047 int strlen
= 0, size
;
10049 impfile
= (WMSFT_ImpFile
*)data
;
10050 impfile
->guid_offs
= implib
->guid
->offset
;
10051 impfile
->lcid
= implib
->lcid
;
10052 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
10054 data
+= sizeof(WMSFT_ImpFile
);
10057 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10061 path
= implib
->name
;
10062 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
),
10063 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
10065 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10068 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
10070 size
= strlen
+ sizeof(INT16
);
10072 size
= (size
+ 4) & ~0x3;
10075 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
10078 implib
->offset
= last_offs
;
10079 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
10083 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10085 MSFT_ImpInfo
*info
;
10086 TLBRefType
*ref_type
;
10089 WMSFT_compile_impfile(This
, file
);
10091 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
10092 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
10094 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
10095 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
10096 if(ref_type
->index
== TLB_REF_USE_GUID
){
10097 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
10098 info
->oGuid
= ref_type
->guid
->offset
;
10100 info
->oGuid
= ref_type
->index
;
10101 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
10107 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10109 file
->guidhash_seg
.len
= 0x80;
10110 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
10111 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
10114 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10116 file
->namehash_seg
.len
= 0x200;
10117 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
10118 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
10121 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
10123 if(contents
&& contents
->len
){
10124 segdir
->offset
= *running_offset
;
10125 segdir
->length
= contents
->len
;
10126 *running_offset
+= segdir
->length
;
10128 segdir
->offset
= -1;
10129 segdir
->length
= 0;
10132 /* TODO: do these ever change? */
10133 segdir
->res08
= -1;
10134 segdir
->res0c
= 0xf;
10137 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10141 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10144 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10148 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10150 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10151 base
->memoffset
+= file_len
;
10158 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10160 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
10161 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
10162 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
10163 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
10164 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
10165 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
10166 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
10167 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
10168 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
10169 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
10170 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
10171 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
10172 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
10173 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
10176 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10178 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10179 WMSFT_TLBFile file
;
10180 DWORD written
, junk_size
, junk_offs
, running_offset
;
10187 TRACE("%p\n", This
);
10189 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10190 if(This
->typeinfos
[i
]->needs_layout
)
10191 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10193 memset(&file
, 0, sizeof(file
));
10195 file
.header
.magic1
= 0x5446534D;
10196 file
.header
.magic2
= 0x00010002;
10197 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10198 file
.header
.lcid2
= This
->set_lcid
;
10199 file
.header
.varflags
= 0x40 | This
->syskind
;
10200 if (This
->HelpFile
)
10201 file
.header
.varflags
|= 0x10;
10202 if (This
->HelpStringDll
)
10203 file
.header
.varflags
|= HELPDLLFLAG
;
10204 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10205 file
.header
.flags
= This
->libflags
;
10206 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10207 file
.header
.helpcontext
= This
->dwHelpContext
;
10208 file
.header
.res44
= 0x20;
10209 file
.header
.res48
= 0x80;
10210 file
.header
.dispatchpos
= This
->dispatch_href
;
10212 WMSFT_compile_namehash(This
, &file
);
10213 /* do name and string compilation to get offsets for other compilations */
10214 hres
= WMSFT_compile_names(This
, &file
);
10216 WMSFT_free_file(&file
);
10220 hres
= WMSFT_compile_strings(This
, &file
);
10222 WMSFT_free_file(&file
);
10226 WMSFT_compile_guidhash(This
, &file
);
10227 hres
= WMSFT_compile_guids(This
, &file
);
10229 WMSFT_free_file(&file
);
10234 file
.header
.helpfile
= This
->HelpFile
->offset
;
10236 file
.header
.helpfile
= -1;
10238 if(This
->DocString
)
10239 file
.header
.helpstring
= This
->DocString
->offset
;
10241 file
.header
.helpstring
= -1;
10243 /* do some more segment compilation */
10244 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10245 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10248 file
.header
.NameOffset
= This
->Name
->offset
;
10250 file
.header
.NameOffset
= -1;
10252 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10255 file
.header
.posguid
= This
->guid
->offset
;
10257 file
.header
.posguid
= -1;
10259 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10260 if(file
.header
.varflags
& HELPDLLFLAG
)
10261 junk_size
+= sizeof(DWORD
);
10263 junk
= heap_alloc_zero(junk_size
);
10264 if(file
.header
.varflags
& HELPDLLFLAG
){
10265 *junk
= This
->HelpStringDll
->offset
;
10274 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10275 WMSFT_compile_impinfo(This
, &file
);
10277 running_offset
= 0;
10279 TRACE("header at: 0x%lx\n", running_offset
);
10280 running_offset
+= sizeof(file
.header
);
10282 TRACE("junk at: 0x%lx\n", running_offset
);
10283 running_offset
+= junk_size
;
10285 TRACE("segdir at: 0x%lx\n", running_offset
);
10286 running_offset
+= sizeof(file
.segdir
);
10288 TRACE("typeinfo at: 0x%lx\n", running_offset
);
10289 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10291 TRACE("guidhashtab at: 0x%lx\n", running_offset
);
10292 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10294 TRACE("guidtab at: 0x%lx\n", running_offset
);
10295 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10297 TRACE("reftab at: 0x%lx\n", running_offset
);
10298 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10300 TRACE("impinfo at: 0x%lx\n", running_offset
);
10301 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10303 TRACE("impfiles at: 0x%lx\n", running_offset
);
10304 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10306 TRACE("namehashtab at: 0x%lx\n", running_offset
);
10307 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10309 TRACE("nametab at: 0x%lx\n", running_offset
);
10310 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10312 TRACE("stringtab at: 0x%lx\n", running_offset
);
10313 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10315 TRACE("typdesc at: 0x%lx\n", running_offset
);
10316 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10318 TRACE("arraydescriptions at: 0x%lx\n", running_offset
);
10319 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10321 TRACE("custdata at: 0x%lx\n", running_offset
);
10322 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10324 TRACE("cdguids at: 0x%lx\n", running_offset
);
10325 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10327 TRACE("res0e at: 0x%lx\n", running_offset
);
10328 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10330 TRACE("res0f at: 0x%lx\n", running_offset
);
10331 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10333 TRACE("aux_seg at: 0x%lx\n", running_offset
);
10335 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10337 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10338 FILE_ATTRIBUTE_NORMAL
, 0);
10339 if (outfile
== INVALID_HANDLE_VALUE
){
10340 WMSFT_free_file(&file
);
10342 return TYPE_E_IOERROR
;
10345 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10347 WMSFT_free_file(&file
);
10348 CloseHandle(outfile
);
10350 return TYPE_E_IOERROR
;
10353 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10356 WMSFT_free_file(&file
);
10357 CloseHandle(outfile
);
10358 return TYPE_E_IOERROR
;
10361 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10363 WMSFT_free_file(&file
);
10364 CloseHandle(outfile
);
10365 return TYPE_E_IOERROR
;
10368 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10369 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10370 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10371 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10372 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10373 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10374 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10375 WMSFT_write_segment(outfile
, &file
.name_seg
);
10376 WMSFT_write_segment(outfile
, &file
.string_seg
);
10377 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10378 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10379 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10380 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10381 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10383 WMSFT_free_file(&file
);
10385 CloseHandle(outfile
);
10390 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10393 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10394 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10398 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10399 REFGUID guid
, VARIANT
*varVal
)
10401 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10404 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10406 if (!guid
|| !varVal
)
10407 return E_INVALIDARG
;
10409 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10411 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10414 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10415 ULONG helpStringContext
)
10417 FIXME("%p, %lu - stub\n", iface
, helpStringContext
);
10421 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10424 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10425 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10428 return E_INVALIDARG
;
10430 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10435 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10436 ICreateTypeLib2_fnQueryInterface
,
10437 ICreateTypeLib2_fnAddRef
,
10438 ICreateTypeLib2_fnRelease
,
10439 ICreateTypeLib2_fnCreateTypeInfo
,
10440 ICreateTypeLib2_fnSetName
,
10441 ICreateTypeLib2_fnSetVersion
,
10442 ICreateTypeLib2_fnSetGuid
,
10443 ICreateTypeLib2_fnSetDocString
,
10444 ICreateTypeLib2_fnSetHelpFileName
,
10445 ICreateTypeLib2_fnSetHelpContext
,
10446 ICreateTypeLib2_fnSetLcid
,
10447 ICreateTypeLib2_fnSetLibFlags
,
10448 ICreateTypeLib2_fnSaveAllChanges
,
10449 ICreateTypeLib2_fnDeleteTypeInfo
,
10450 ICreateTypeLib2_fnSetCustData
,
10451 ICreateTypeLib2_fnSetHelpStringContext
,
10452 ICreateTypeLib2_fnSetHelpStringDll
10455 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10456 REFIID riid
, void **object
)
10458 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10460 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10463 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10465 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10467 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10470 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10472 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10474 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10477 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10480 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10482 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10484 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10489 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10492 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10496 TRACE("%p %x\n", This
, typeFlags
);
10498 if (typeFlags
& TYPEFLAG_FDUAL
) {
10500 ITypeInfo
*dispatch
;
10504 hres
= LoadTypeLib(L
"stdole2.tlb", &stdole
);
10508 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10509 ITypeLib_Release(stdole
);
10513 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10514 ITypeInfo_Release(dispatch
);
10519 old_flags
= This
->typeattr
.wTypeFlags
;
10520 This
->typeattr
.wTypeFlags
= typeFlags
;
10522 hres
= ICreateTypeInfo2_LayOut(iface
);
10523 if (FAILED(hres
)) {
10524 This
->typeattr
.wTypeFlags
= old_flags
;
10531 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10534 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10536 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10539 return E_INVALIDARG
;
10541 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10546 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10549 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10551 TRACE("%p, %ld.\n", iface
, helpContext
);
10553 This
->dwHelpContext
= helpContext
;
10558 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10559 WORD majorVerNum
, WORD minorVerNum
)
10561 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10563 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10565 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10566 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10571 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10572 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10574 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10576 ITypeLib
*container
;
10577 TLBRefType
*ref_type
;
10579 TYPEATTR
*typeattr
;
10583 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10585 if (!typeInfo
|| !refType
)
10586 return E_INVALIDARG
;
10588 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10592 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10593 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10595 ITypeLib_Release(container
);
10597 *refType
= target
->hreftype
;
10602 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10603 if (FAILED(hres
)) {
10604 ITypeLib_Release(container
);
10608 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10609 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10610 implib
->lcid
== libattr
->lcid
&&
10611 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10612 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10616 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10617 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10619 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10620 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10621 implib
->name
= SysAllocString(our_container
->path
);
10623 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10624 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10626 implib
->name
= NULL
;
10627 TRACE("QueryPathOfRegTypeLib failed, no name stored: %#lx.\n", hres
);
10631 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10632 implib
->lcid
= libattr
->lcid
;
10633 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10634 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10636 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10639 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10640 ITypeLib_Release(container
);
10642 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10647 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10648 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10649 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10650 ref_type
->tkind
== typeattr
->typekind
)
10655 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10656 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10658 ref_type
->tkind
= typeattr
->typekind
;
10659 ref_type
->pImpTLInfo
= implib
;
10660 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10662 ref_type
->index
= TLB_REF_USE_GUID
;
10664 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10666 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10669 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10671 *refType
= ref_type
->reference
| 0x1;
10673 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10674 This
->pTypeLib
->dispatch_href
= *refType
;
10679 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10680 UINT index
, FUNCDESC
*funcDesc
)
10682 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10683 TLBFuncDesc tmp_func_desc
, *func_desc
;
10688 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10690 if (!funcDesc
|| funcDesc
->oVft
& 3)
10691 return E_INVALIDARG
;
10693 switch (This
->typeattr
.typekind
) {
10695 if (funcDesc
->funckind
!= FUNC_STATIC
)
10696 return TYPE_E_BADMODULEKIND
;
10698 case TKIND_DISPATCH
:
10699 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10700 return TYPE_E_BADMODULEKIND
;
10703 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10704 return TYPE_E_BADMODULEKIND
;
10707 if (index
> This
->typeattr
.cFuncs
)
10708 return TYPE_E_ELEMENTNOTFOUND
;
10710 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10711 !funcDesc
->cParams
)
10712 return TYPE_E_INCONSISTENTPROPFUNCS
;
10715 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10716 funcDesc
->oVft
% 8 != 0)
10717 return E_INVALIDARG
;
10720 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10721 TLBFuncDesc_Constructor(&tmp_func_desc
);
10723 tmp_func_desc
.funcdesc
= *funcDesc
;
10725 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10726 tmp_func_desc
.funcdesc
.oVft
|= 1;
10728 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10729 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10730 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10732 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10733 tmp_func_desc
.funcdesc
.cScodes
= 0;
10736 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10737 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10738 buf_size
+= sizeof(ELEMDESC
);
10739 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10741 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10742 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10744 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10745 if (FAILED(hres
)) {
10746 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10747 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10751 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10752 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10753 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10754 if (FAILED(hres
)) {
10755 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10756 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10759 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10760 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10761 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10762 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10763 if (FAILED(hres
)) {
10764 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10765 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10771 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10773 if (This
->funcdescs
) {
10774 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10775 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10777 if (index
< This
->typeattr
.cFuncs
) {
10778 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10779 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10780 func_desc
= This
->funcdescs
+ index
;
10782 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10784 /* move custdata lists to the new memory location */
10785 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10787 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
10790 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10792 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10793 list_init(&func_desc
->custdata_list
);
10795 ++This
->typeattr
.cFuncs
;
10797 This
->needs_layout
= TRUE
;
10802 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10803 UINT index
, HREFTYPE refType
)
10805 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10806 TLBImplType
*impl_type
;
10809 TRACE("%p, %u, %ld.\n", iface
, index
, refType
);
10811 switch(This
->typeattr
.typekind
){
10812 case TKIND_COCLASS
: {
10814 FIXME("Unhandled index: -1\n");
10818 if(index
!= This
->typeattr
.cImplTypes
)
10819 return TYPE_E_ELEMENTNOTFOUND
;
10823 case TKIND_INTERFACE
:
10824 case TKIND_DISPATCH
:
10825 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10826 return TYPE_E_ELEMENTNOTFOUND
;
10829 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10833 if (This
->impltypes
){
10836 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10837 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10839 if (index
< This
->typeattr
.cImplTypes
) {
10840 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10841 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10842 impl_type
= This
->impltypes
+ index
;
10844 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10846 /* move custdata lists to the new memory location */
10847 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10849 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
10852 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10854 memset(impl_type
, 0, sizeof(TLBImplType
));
10855 TLBImplType_Constructor(impl_type
);
10856 impl_type
->hRef
= refType
;
10858 ++This
->typeattr
.cImplTypes
;
10860 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10861 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10863 hres
= ICreateTypeInfo2_LayOut(iface
);
10870 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10871 UINT index
, INT implTypeFlags
)
10873 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10874 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10876 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10878 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10879 return TYPE_E_BADMODULEKIND
;
10881 if (index
>= This
->typeattr
.cImplTypes
)
10882 return TYPE_E_ELEMENTNOTFOUND
;
10884 impl_type
->implflags
= implTypeFlags
;
10889 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10892 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10894 TRACE("%p %d\n", This
, alignment
);
10896 This
->typeattr
.cbAlignment
= alignment
;
10901 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10904 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10906 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10909 return E_INVALIDARG
;
10911 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10913 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10918 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10919 UINT index
, VARDESC
*varDesc
)
10921 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10922 TLBVarDesc
*var_desc
;
10925 TRACE("%p %u %p\n", This
, index
, varDesc
);
10927 if (This
->vardescs
){
10930 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10931 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
10933 if (index
< This
->typeattr
.cVars
) {
10934 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10935 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
10936 var_desc
= This
->vardescs
+ index
;
10938 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
10940 /* move custdata lists to the new memory location */
10941 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
10943 TLB_relink_custdata(&This
->vardescs
[i
].custdata_list
);
10946 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10948 TLBVarDesc_Constructor(var_desc
);
10949 hr
= TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10952 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10954 ++This
->typeattr
.cVars
;
10956 This
->needs_layout
= TRUE
;
10961 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10962 UINT index
, LPOLESTR
*names
, UINT numNames
)
10964 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10965 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10968 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10971 return E_INVALIDARG
;
10973 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
10974 return TYPE_E_ELEMENTNOTFOUND
;
10976 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10977 if(numNames
> func_desc
->funcdesc
.cParams
)
10978 return TYPE_E_ELEMENTNOTFOUND
;
10980 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10981 return TYPE_E_ELEMENTNOTFOUND
;
10983 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
10984 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10985 if (iter
->Name
&& !wcscmp(TLB_get_bstr(iter
->Name
), *names
)) {
10986 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10987 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10988 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10990 return TYPE_E_AMBIGUOUSNAME
;
10994 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10996 for (i
= 1; i
< numNames
; ++i
) {
10997 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10998 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
11004 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
11005 UINT index
, LPOLESTR name
)
11007 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11009 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
11012 return E_INVALIDARG
;
11014 if(index
>= This
->typeattr
.cVars
)
11015 return TYPE_E_ELEMENTNOTFOUND
;
11017 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11021 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
11022 TYPEDESC
*tdescAlias
)
11024 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11027 TRACE("%p %p\n", This
, tdescAlias
);
11030 return E_INVALIDARG
;
11032 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
11033 return TYPE_E_BADMODULEKIND
;
11035 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
11039 heap_free(This
->tdescAlias
);
11040 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
11041 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
11046 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
11047 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
11049 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11050 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
11054 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
11055 UINT index
, LPOLESTR docString
)
11057 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11058 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11060 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11063 return E_INVALIDARG
;
11065 if(index
>= This
->typeattr
.cFuncs
)
11066 return TYPE_E_ELEMENTNOTFOUND
;
11068 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11073 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
11074 UINT index
, LPOLESTR docString
)
11076 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11077 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11079 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11082 return E_INVALIDARG
;
11084 if(index
>= This
->typeattr
.cVars
)
11085 return TYPE_E_ELEMENTNOTFOUND
;
11087 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11092 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
11093 UINT index
, DWORD helpContext
)
11095 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11096 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11098 TRACE("%p, %u, %ld.\n", iface
, index
, helpContext
);
11100 if(index
>= This
->typeattr
.cFuncs
)
11101 return TYPE_E_ELEMENTNOTFOUND
;
11103 func_desc
->helpcontext
= helpContext
;
11108 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
11109 UINT index
, DWORD helpContext
)
11111 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11112 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11114 TRACE("%p, %u, %ld.\n", iface
, index
, helpContext
);
11116 if(index
>= This
->typeattr
.cVars
)
11117 return TYPE_E_ELEMENTNOTFOUND
;
11119 var_desc
->HelpContext
= helpContext
;
11124 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
11125 UINT index
, BSTR bstrMops
)
11127 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11128 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
11132 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
11135 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11137 TRACE("%p %p\n", This
, idlDesc
);
11140 return E_INVALIDARG
;
11142 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11143 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11148 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11150 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11151 ITypeInfo2
*tinfo
= &This
->ITypeInfo2_iface
;
11152 TLBFuncDesc
*func_desc
;
11153 UINT user_vft
= 0, i
, depth
= 0;
11154 HRESULT hres
= S_OK
;
11156 TRACE("%p\n", This
);
11158 This
->needs_layout
= FALSE
;
11160 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11165 hres
= ITypeInfo2_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11167 if (SUCCEEDED(hres
)) {
11168 hres
= ITypeInfo2_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11170 if (SUCCEEDED(hres
)) {
11171 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11172 if (FAILED(hres
)) {
11173 ITypeInfo_Release(inh
);
11176 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11177 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11181 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11182 if(SUCCEEDED(hres
)){
11184 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11185 if(SUCCEEDED(hres
)){
11186 ITypeInfo_Release(inh
);
11190 }while(SUCCEEDED(hres
));
11193 ITypeInfo_Release(inh
);
11194 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11195 This
->typeattr
.cbSizeVft
= 0;
11199 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11200 This
->typeattr
.cbSizeVft
= 0;
11204 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11205 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11207 This
->typeattr
.cbSizeVft
= 0;
11209 func_desc
= This
->funcdescs
;
11211 while (i
< This
->typeattr
.cFuncs
) {
11212 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11213 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11215 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11216 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11218 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11220 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11223 BOOL reset
= FALSE
;
11225 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11227 iter
= This
->funcdescs
;
11228 while (j
< This
->typeattr
.cFuncs
) {
11229 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11231 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11234 ++func_desc
->funcdesc
.memid
;
11235 iter
= This
->funcdescs
;
11248 if (user_vft
> This
->typeattr
.cbSizeVft
)
11249 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11251 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11252 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11253 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11255 BOOL reset
= FALSE
;
11258 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11260 iter
= This
->vardescs
;
11261 while (j
< This
->typeattr
.cVars
) {
11262 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11264 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11267 ++var_desc
->vardesc
.memid
;
11268 iter
= This
->vardescs
;
11281 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11284 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11287 TRACE("%p %u\n", This
, index
);
11289 if (index
>= This
->typeattr
.cFuncs
)
11290 return TYPE_E_ELEMENTNOTFOUND
;
11292 typeinfo_release_funcdesc(&This
->funcdescs
[index
]);
11294 --This
->typeattr
.cFuncs
;
11295 if (index
!= This
->typeattr
.cFuncs
)
11297 memmove(This
->funcdescs
+ index
, This
->funcdescs
+ index
+ 1,
11298 sizeof(*This
->funcdescs
) * (This
->typeattr
.cFuncs
- index
));
11299 for (i
= index
; i
< This
->typeattr
.cFuncs
; ++i
)
11300 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
11303 This
->needs_layout
= TRUE
;
11308 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11309 MEMBERID memid
, INVOKEKIND invKind
)
11311 FIXME("%p, %#lx, %d - stub\n", iface
, memid
, invKind
);
11315 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11318 FIXME("%p, %u - stub\n", iface
, index
);
11322 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11325 FIXME("%p, %#lx - stub\n", iface
, memid
);
11329 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11332 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11335 TRACE("%p %u\n", This
, index
);
11337 if (index
>= This
->typeattr
.cImplTypes
)
11338 return TYPE_E_ELEMENTNOTFOUND
;
11340 TLB_FreeCustData(&This
->impltypes
[index
].custdata_list
);
11341 --This
->typeattr
.cImplTypes
;
11343 if (index
< This
->typeattr
.cImplTypes
)
11345 memmove(This
->impltypes
+ index
, This
->impltypes
+ index
+ 1, (This
->typeattr
.cImplTypes
- index
) *
11346 sizeof(*This
->impltypes
));
11347 for (i
= index
; i
< This
->typeattr
.cImplTypes
; ++i
)
11348 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
11354 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11355 REFGUID guid
, VARIANT
*varVal
)
11359 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11361 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11363 if (!guid
|| !varVal
)
11364 return E_INVALIDARG
;
11366 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11368 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11371 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11372 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11374 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11375 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11379 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11380 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11382 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11383 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11387 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11388 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11390 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11391 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11395 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11396 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11398 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11399 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11403 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11404 ULONG helpStringContext
)
11406 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11408 TRACE("%p, %lu.\n", iface
, helpStringContext
);
11410 This
->dwHelpStringContext
= helpStringContext
;
11415 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11416 UINT index
, ULONG helpStringContext
)
11418 FIXME("%p, %u, %lu - stub\n", iface
, index
, helpStringContext
);
11422 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11423 UINT index
, ULONG helpStringContext
)
11425 FIXME("%p, %u, %lu - stub\n", iface
, index
, helpStringContext
);
11429 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11431 FIXME("%p - stub\n", iface
);
11435 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11438 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11440 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11443 return E_INVALIDARG
;
11445 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11450 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11451 ICreateTypeInfo2_fnQueryInterface
,
11452 ICreateTypeInfo2_fnAddRef
,
11453 ICreateTypeInfo2_fnRelease
,
11454 ICreateTypeInfo2_fnSetGuid
,
11455 ICreateTypeInfo2_fnSetTypeFlags
,
11456 ICreateTypeInfo2_fnSetDocString
,
11457 ICreateTypeInfo2_fnSetHelpContext
,
11458 ICreateTypeInfo2_fnSetVersion
,
11459 ICreateTypeInfo2_fnAddRefTypeInfo
,
11460 ICreateTypeInfo2_fnAddFuncDesc
,
11461 ICreateTypeInfo2_fnAddImplType
,
11462 ICreateTypeInfo2_fnSetImplTypeFlags
,
11463 ICreateTypeInfo2_fnSetAlignment
,
11464 ICreateTypeInfo2_fnSetSchema
,
11465 ICreateTypeInfo2_fnAddVarDesc
,
11466 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11467 ICreateTypeInfo2_fnSetVarName
,
11468 ICreateTypeInfo2_fnSetTypeDescAlias
,
11469 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11470 ICreateTypeInfo2_fnSetFuncDocString
,
11471 ICreateTypeInfo2_fnSetVarDocString
,
11472 ICreateTypeInfo2_fnSetFuncHelpContext
,
11473 ICreateTypeInfo2_fnSetVarHelpContext
,
11474 ICreateTypeInfo2_fnSetMops
,
11475 ICreateTypeInfo2_fnSetTypeIdldesc
,
11476 ICreateTypeInfo2_fnLayOut
,
11477 ICreateTypeInfo2_fnDeleteFuncDesc
,
11478 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11479 ICreateTypeInfo2_fnDeleteVarDesc
,
11480 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11481 ICreateTypeInfo2_fnDeleteImplType
,
11482 ICreateTypeInfo2_fnSetCustData
,
11483 ICreateTypeInfo2_fnSetFuncCustData
,
11484 ICreateTypeInfo2_fnSetParamCustData
,
11485 ICreateTypeInfo2_fnSetVarCustData
,
11486 ICreateTypeInfo2_fnSetImplTypeCustData
,
11487 ICreateTypeInfo2_fnSetHelpStringContext
,
11488 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11489 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11490 ICreateTypeInfo2_fnInvalidate
,
11491 ICreateTypeInfo2_fnSetName
11494 /******************************************************************************
11495 * ClearCustData (OLEAUT32.171)
11497 * Clear a custom data type's data.
11500 * lpCust [I] The custom data type instance
11505 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11507 if (lpCust
&& lpCust
->cCustData
)
11509 if (lpCust
->prgCustData
)
11513 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11514 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11516 CoTaskMemFree(lpCust
->prgCustData
);
11517 lpCust
->prgCustData
= NULL
;
11519 lpCust
->cCustData
= 0;