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
68 #include "wine/debug.h"
71 #include "wine/heap.h"
72 #include "wine/list.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
75 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
89 WORD type_id
; /* Type identifier */
90 WORD count
; /* Number of resources of this type */
91 DWORD resloader
; /* SetResourceHandler() */
97 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
98 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
99 static void TLB_FreeVarDesc(VARDESC
*);
101 /****************************************************************************
104 * Takes p_iVal (which is in little endian) and returns it
105 * in the host machine's byte order.
107 #ifdef WORDS_BIGENDIAN
108 static WORD
FromLEWord(WORD p_iVal
)
110 return (((p_iVal
& 0x00FF) << 8) |
111 ((p_iVal
& 0xFF00) >> 8));
115 static DWORD
FromLEDWord(DWORD p_iVal
)
117 return (((p_iVal
& 0x000000FF) << 24) |
118 ((p_iVal
& 0x0000FF00) << 8) |
119 ((p_iVal
& 0x00FF0000) >> 8) |
120 ((p_iVal
& 0xFF000000) >> 24));
123 #define FromLEWord(X) (X)
124 #define FromLEDWord(X) (X)
127 #define DISPATCH_HREF_OFFSET 0x01000000
128 #define DISPATCH_HREF_MASK 0xff000000
130 /****************************************************************************
133 * Fix byte order in any structure if necessary
135 #ifdef WORDS_BIGENDIAN
136 static void FromLEWords(void *p_Val
, int p_iSize
)
140 p_iSize
/= sizeof(WORD
);
143 *Val
= FromLEWord(*Val
);
150 static void FromLEDWords(void *p_Val
, int p_iSize
)
154 p_iSize
/= sizeof(DWORD
);
157 *Val
= FromLEDWord(*Val
);
163 #define FromLEWords(X,Y) /*nothing*/
164 #define FromLEDWords(X,Y) /*nothing*/
168 * Find a typelib key which matches a requested maj.min version.
170 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
175 INT best_maj
= -1, best_min
= -1;
178 lstrcpyW( buffer
, L
"Typelib\\" );
179 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
181 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
184 len
= sizeof(key_name
);
186 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
190 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
192 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
194 if (*wMaj
== 0xffff && *wMin
== 0xffff)
196 if (v_maj
> best_maj
) best_maj
= v_maj
;
197 if (v_min
> best_min
) best_min
= v_min
;
199 else if (*wMaj
== v_maj
)
206 break; /* exact match */
208 if (*wMin
!= 0xffff && v_min
>= *wMin
&& v_min
> best_min
) best_min
= v_min
;
211 len
= sizeof(key_name
);
215 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
217 if (*wMaj
== 0xffff && *wMin
== 0xffff)
219 if (best_maj
>= 0 && best_min
>= 0)
227 if (*wMaj
== best_maj
&& best_min
>= 0)
235 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
236 /* buffer must be at least 60 characters long */
237 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
239 lstrcpyW( buffer
, L
"Typelib\\" );
240 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
241 swprintf( buffer
+ lstrlenW(buffer
), 20, L
"\\%x.%x", wMaj
, wMin
);
245 /* get the path of an interface key, in the form "Interface\\<guid>" */
246 /* buffer must be at least 50 characters long */
247 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
249 lstrcpyW( buffer
, L
"Interface\\" );
250 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
254 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
255 /* buffer must be at least 16 characters long */
256 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
258 swprintf( buffer
, 16, L
"%lx\\", lcid
);
261 case SYS_WIN16
: lstrcatW( buffer
, L
"win16" ); break;
262 case SYS_WIN32
: lstrcatW( buffer
, L
"win32" ); break;
263 case SYS_WIN64
: lstrcatW( buffer
, L
"win64" ); break;
265 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
271 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
273 struct tlibredirect_data
287 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
288 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
289 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
291 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
295 WCHAR Path
[MAX_PATH
];
298 TRACE_(typelib
)("%s, %x.%x, %#lx, %p\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
302 ACTCTX_SECTION_KEYED_DATA data
;
304 data
.cbSize
= sizeof(data
);
305 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
307 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
311 if ((wMaj
!= 0xffff || wMin
!= 0xffff) && (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
))
312 return TYPE_E_LIBNOTREGISTERED
;
314 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
315 len
= SearchPathW( NULL
, nameW
, NULL
, ARRAY_SIZE( Path
), Path
, NULL
);
316 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
318 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
319 *path
= SysAllocString( Path
);
324 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
325 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
327 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
328 if (res
== ERROR_FILE_NOT_FOUND
)
330 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
331 return TYPE_E_LIBNOTREGISTERED
;
333 else if (res
!= ERROR_SUCCESS
)
335 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
336 return TYPE_E_REGISTRYACCESS
;
341 LONG dwPathLen
= sizeof(Path
);
343 get_lcid_subkey( myLCID
, syskind
, buffer
);
345 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
349 else if (myLCID
== lcid
)
351 /* try with sub-langid */
352 myLCID
= SUBLANGID(lcid
);
354 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
356 /* try with system langid */
366 *path
= SysAllocString( Path
);
371 TRACE_(typelib
)("-- %#lx\n", hr
);
375 /****************************************************************************
376 * QueryPathOfRegTypeLib [OLEAUT32.164]
378 * Gets the path to a registered type library.
381 * guid [I] referenced guid
382 * wMaj [I] major version
383 * wMin [I] minor version
385 * path [O] path of typelib
389 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
390 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
393 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
397 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
402 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
405 /******************************************************************************
406 * CreateTypeLib [OLEAUT32.160] creates a typelib
412 HRESULT WINAPI
CreateTypeLib(
413 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
415 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
419 /******************************************************************************
420 * LoadTypeLib [OLEAUT32.161]
422 * Loads a type library
425 * szFile [I] Name of file to load from.
426 * pptLib [O] Pointer that receives ITypeLib object on success.
433 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
435 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
437 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
438 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
441 /******************************************************************************
442 * LoadTypeLibEx [OLEAUT32.183]
444 * Loads and optionally registers a type library
450 HRESULT WINAPI
LoadTypeLibEx(
451 LPCOLESTR szFile
, /* [in] Name of file to load from */
452 REGKIND regkind
, /* [in] Specify kind of registration */
453 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
455 WCHAR szPath
[MAX_PATH
+1];
458 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
460 if (!szFile
|| !pptLib
)
465 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
470 case REGKIND_DEFAULT
:
471 /* don't register typelibs supplied with full path. Experimentation confirms the following */
472 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
473 (szFile
[0] && (szFile
[1] == ':'))) break;
474 /* else fall-through */
476 case REGKIND_REGISTER
:
477 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
479 ITypeLib_Release(*pptLib
);
487 TRACE(" returns %#lx\n",res
);
491 /******************************************************************************
492 * LoadRegTypeLib [OLEAUT32.162]
494 * Loads a registered type library.
497 * rguid [I] GUID of the registered type library.
498 * wVerMajor [I] major version.
499 * wVerMinor [I] minor version.
500 * lcid [I] locale ID.
501 * ppTLib [O] pointer that receives an ITypeLib object on success.
505 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
508 HRESULT WINAPI
LoadRegTypeLib(
520 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
524 res
= LoadTypeLib(bstr
, ppTLib
);
527 if ((wVerMajor
!=0xffff || wVerMinor
!=0xffff) && *ppTLib
)
531 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
534 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
535 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
539 ITypeLib_Release(*ppTLib
);
541 res
= TYPE_E_LIBNOTREGISTERED
;
547 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
552 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
557 get_interface_key( &tattr
->guid
, keyName
);
558 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
559 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
561 const WCHAR
*proxy_clsid
;
563 if (tattr
->typekind
== TKIND_INTERFACE
|| (tattr
->wTypeFlags
& TYPEFLAG_FDUAL
))
564 proxy_clsid
= L
"{00020424-0000-0000-C000-000000000046}";
566 proxy_clsid
= L
"{00020420-0000-0000-C000-000000000046}";
569 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
570 (BYTE
*)name
, (lstrlenW(name
)+1) * sizeof(OLECHAR
));
572 if (!RegCreateKeyExW(key
, L
"ProxyStubClsid", 0, NULL
, 0, KEY_WRITE
| flag
, NULL
, &subKey
, NULL
))
574 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
, (const BYTE
*)proxy_clsid
, (lstrlenW(proxy_clsid
) + 1) * sizeof(WCHAR
));
578 if (!RegCreateKeyExW(key
, L
"ProxyStubClsid32", 0, NULL
, 0, KEY_WRITE
| flag
, NULL
, &subKey
, NULL
))
580 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
, (const BYTE
*)proxy_clsid
, (lstrlenW(proxy_clsid
) + 1) * sizeof(WCHAR
));
584 if (RegCreateKeyExW(key
, L
"TypeLib", 0, NULL
, 0,
585 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
589 StringFromGUID2(&libattr
->guid
, buffer
, 40);
590 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
591 (BYTE
*)buffer
, (lstrlenW(buffer
)+1) * sizeof(WCHAR
));
592 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%x.%x", libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
593 RegSetValueExW(subKey
, L
"Version", 0, REG_SZ
, (BYTE
*)buffer
, (lstrlenW(buffer
)+1) * sizeof(WCHAR
));
601 /******************************************************************************
602 * RegisterTypeLib [OLEAUT32.163]
603 * Adds information about a type library to the System Registry
605 * Docs: ITypeLib FAR * ptlib
606 * Docs: OLECHAR FAR* szFullPath
607 * Docs: OLECHAR FAR* szHelpDir
613 HRESULT WINAPI
RegisterTypeLib(ITypeLib
*ptlib
, const WCHAR
*szFullPath
, const WCHAR
*szHelpDir
)
624 if (ptlib
== NULL
|| szFullPath
== NULL
)
627 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
630 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
633 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
634 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
639 /* Set the human-readable name of the typelib to
640 the typelib's doc, if it exists, else to the typelib's name. */
641 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, &libName
, &doc
, NULL
, NULL
)))
643 else if (doc
|| libName
)
645 WCHAR
*name
= doc
? doc
: libName
;
647 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
648 (BYTE
*)name
, (lstrlenW(name
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
652 SysFreeString(libName
);
655 /* Make up the name of the typelib path subkey */
656 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
658 /* Create the typelib path subkey */
659 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
660 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
662 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
663 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
671 /* Create the flags subkey */
672 if (res
== S_OK
&& RegCreateKeyExW(key
, L
"FLAGS", 0, NULL
, 0,
673 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
677 /* FIXME: is %u correct? */
678 swprintf(buf
, ARRAY_SIZE(buf
), L
"%u", attr
->wLibFlags
);
679 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
680 (BYTE
*)buf
, (lstrlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
688 /* create the helpdir subkey */
689 if (res
== S_OK
&& RegCreateKeyExW(key
, L
"HELPDIR", 0, NULL
, 0,
690 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
692 BSTR freeHelpDir
= NULL
;
695 /* if we created a new key, and helpDir was null, set the helpdir
696 to the directory which contains the typelib. However,
697 if we just opened an existing key, we leave the helpdir alone */
698 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
699 szHelpDir
= freeHelpDir
= SysAllocString(szFullPath
);
700 file_name
= wcsrchr(szHelpDir
, '\\');
701 if (file_name
&& file_name
[1]) {
702 /* possible remove a numeric \index (resource-id) */
703 WCHAR
*end_ptr
= file_name
+ 1;
704 while ('0' <= *end_ptr
&& *end_ptr
<= '9') end_ptr
++;
708 file_name
= wcsrchr(szHelpDir
, '\\');
715 /* if we have an szHelpDir, set it! */
716 if (szHelpDir
!= NULL
) {
717 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
718 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
723 SysFreeString(freeHelpDir
);
734 /* register OLE Automation-compatible interfaces for this typelib */
735 types
= ITypeLib_GetTypeInfoCount(ptlib
);
736 for (tidx
=0; tidx
<types
; tidx
++) {
737 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
738 LPOLESTR name
= NULL
;
739 ITypeInfo
*tinfo
= NULL
;
741 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
744 case TKIND_INTERFACE
:
745 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
746 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
750 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
751 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
755 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
760 TYPEATTR
*tattr
= NULL
;
761 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
764 TRACE_(typelib
)("guid=%s, flags=%04x (",
765 debugstr_guid(&tattr
->guid
),
768 if (TRACE_ON(typelib
)) {
769 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
789 /* Register all dispinterfaces (which includes dual interfaces) and
790 oleautomation interfaces */
791 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
792 kind
== TKIND_DISPATCH
)
795 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
797 /* register interface<->typelib coupling */
798 TLB_register_interface(attr
, name
, tattr
, 0);
800 /* register TLBs into the opposite registry view, too */
801 if(opposite
== KEY_WOW64_32KEY
||
802 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
803 TLB_register_interface(attr
, name
, tattr
, opposite
);
806 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
809 ITypeInfo_Release(tinfo
);
816 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
821 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
823 WCHAR subKeyName
[50];
826 /* the path to the type */
827 get_interface_key( guid
, subKeyName
);
829 /* Delete its bits */
830 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
833 RegDeleteKeyW(subKey
, L
"ProxyStubClsid");
834 RegDeleteKeyW(subKey
, L
"ProxyStubClsid32");
835 RegDeleteKeyW(subKey
, L
"TypeLib");
837 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
840 /******************************************************************************
841 * UnRegisterTypeLib [OLEAUT32.186]
842 * Removes information about a type library from the System Registry
849 HRESULT WINAPI
UnRegisterTypeLib(
850 REFGUID libid
, /* [in] Guid of the library */
851 WORD wVerMajor
, /* [in] major version */
852 WORD wVerMinor
, /* [in] minor version */
853 LCID lcid
, /* [in] locale id */
856 BSTR tlibPath
= NULL
;
859 WCHAR subKeyName
[50];
862 BOOL deleteOtherStuff
;
864 TYPEATTR
* typeAttr
= NULL
;
866 ITypeInfo
* typeInfo
= NULL
;
867 ITypeLib
* typeLib
= NULL
;
870 TRACE("(IID: %s)\n",debugstr_guid(libid
));
872 /* Create the path to the key */
873 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
875 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
877 TRACE("Unsupported syskind %i\n", syskind
);
878 result
= E_INVALIDARG
;
882 /* get the path to the typelib on disk */
883 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
884 result
= E_INVALIDARG
;
888 /* Try and open the key to the type library. */
889 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
890 result
= E_INVALIDARG
;
894 /* Try and load the type library */
895 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
896 result
= TYPE_E_INVALIDSTATE
;
900 /* remove any types registered with this typelib */
901 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
902 for (i
=0; i
<numTypes
; i
++) {
903 /* get the kind of type */
904 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
908 /* skip non-interfaces, and get type info for the type */
909 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
912 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
915 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
919 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
920 kind
== TKIND_DISPATCH
)
923 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
925 TLB_unregister_interface(&typeAttr
->guid
, 0);
927 /* unregister TLBs into the opposite registry view, too */
928 if(opposite
== KEY_WOW64_32KEY
||
929 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
930 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
935 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
937 if (typeInfo
) ITypeInfo_Release(typeInfo
);
941 /* Now, delete the type library path subkey */
942 get_lcid_subkey( lcid
, syskind
, subKeyName
);
943 RegDeleteKeyW(key
, subKeyName
);
944 *wcsrchr( subKeyName
, '\\' ) = 0; /* remove last path component */
945 RegDeleteKeyW(key
, subKeyName
);
947 /* check if there is anything besides the FLAGS/HELPDIR keys.
948 If there is, we don't delete them */
949 tmpLength
= ARRAY_SIZE(subKeyName
);
950 deleteOtherStuff
= TRUE
;
952 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
953 tmpLength
= ARRAY_SIZE(subKeyName
);
955 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
956 if (!wcscmp(subKeyName
, L
"FLAGS")) continue;
957 if (!wcscmp(subKeyName
, L
"HELPDIR")) continue;
958 deleteOtherStuff
= FALSE
;
962 /* only delete the other parts of the key if we're absolutely sure */
963 if (deleteOtherStuff
) {
964 RegDeleteKeyW(key
, L
"FLAGS");
965 RegDeleteKeyW(key
, L
"HELPDIR");
969 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
970 *wcsrchr( keyName
, '\\' ) = 0; /* remove last path component */
971 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
975 SysFreeString(tlibPath
);
976 if (typeLib
) ITypeLib_Release(typeLib
);
977 if (key
) RegCloseKey(key
);
981 /******************************************************************************
982 * RegisterTypeLibForUser [OLEAUT32.442]
983 * Adds information about a type library to the user registry
985 * Docs: ITypeLib FAR * ptlib
986 * Docs: OLECHAR FAR* szFullPath
987 * Docs: OLECHAR FAR* szHelpDir
993 HRESULT WINAPI
RegisterTypeLibForUser(
994 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
995 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
996 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
999 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1000 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1001 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1004 /******************************************************************************
1005 * UnRegisterTypeLibForUser [OLEAUT32.443]
1006 * Removes information about a type library from the user registry
1012 HRESULT WINAPI
UnRegisterTypeLibForUser(
1013 REFGUID libid
, /* [in] GUID of the library */
1014 WORD wVerMajor
, /* [in] major version */
1015 WORD wVerMinor
, /* [in] minor version */
1016 LCID lcid
, /* [in] locale id */
1019 FIXME("%s, %u, %u, %#lx, %u unregistering the typelib system-wide\n",
1020 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1021 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1024 /*======================= ITypeLib implementation =======================*/
1026 typedef struct tagTLBGuid
{
1033 typedef struct tagTLBCustData
1040 /* data structure for import typelibs */
1041 typedef struct tagTLBImpLib
1043 int offset
; /* offset in the file (MSFT)
1044 offset in nametable (SLTG)
1045 just used to identify library while reading
1047 TLBGuid
*guid
; /* libid */
1048 BSTR name
; /* name */
1050 LCID lcid
; /* lcid of imported typelib */
1052 WORD wVersionMajor
; /* major version number */
1053 WORD wVersionMinor
; /* minor version number */
1055 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1056 NULL if not yet loaded */
1060 typedef struct tagTLBString
{
1066 /* internal ITypeLib data */
1067 typedef struct tagITypeLibImpl
1069 ITypeLib2 ITypeLib2_iface
;
1070 ITypeComp ITypeComp_iface
;
1071 ICreateTypeLib2 ICreateTypeLib2_iface
;
1082 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1083 * exported to the application as a UNICODE string.
1085 struct list string_list
;
1086 struct list name_list
;
1087 struct list guid_list
;
1089 const TLBString
*Name
;
1090 const TLBString
*DocString
;
1091 const TLBString
*HelpFile
;
1092 const TLBString
*HelpStringDll
;
1093 DWORD dwHelpContext
;
1094 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1095 struct tagITypeInfoImpl
**typeinfos
;
1096 struct list custdata_list
;
1097 struct list implib_list
;
1098 int ctTypeDesc
; /* number of items in type desc array */
1099 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1100 library. Only used while reading MSFT
1102 struct list ref_list
; /* list of ref types in this typelib */
1103 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1106 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1112 static const ITypeLib2Vtbl tlbvt
;
1113 static const ITypeCompVtbl tlbtcvt
;
1114 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1116 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1118 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1121 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1123 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1126 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1128 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1131 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1133 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1136 /* ITypeLib methods */
1137 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1138 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1140 /*======================= ITypeInfo implementation =======================*/
1142 /* data for referenced types */
1143 typedef struct tagTLBRefType
1145 INT index
; /* Type index for internal ref or for external ref
1146 it the format is SLTG. -2 indicates to
1150 TLBGuid
*guid
; /* guid of the referenced type */
1151 /* if index == TLB_REF_USE_GUID */
1153 HREFTYPE reference
; /* The href of this ref */
1154 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1155 TLB_REF_INTERNAL for internal refs
1156 TLB_REF_NOT_FOUND for broken refs */
1161 #define TLB_REF_USE_GUID -2
1163 #define TLB_REF_INTERNAL (void*)-2
1164 #define TLB_REF_NOT_FOUND (void*)-1
1166 /* internal Parameter data */
1167 typedef struct tagTLBParDesc
1169 const TLBString
*Name
;
1170 struct list custdata_list
;
1173 /* internal Function data */
1174 typedef struct tagTLBFuncDesc
1176 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1177 const TLBString
*Name
; /* the name of this function */
1178 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1180 int HelpStringContext
;
1181 const TLBString
*HelpString
;
1182 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1183 struct list custdata_list
;
1186 /* internal Variable data */
1187 typedef struct tagTLBVarDesc
1189 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1190 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1191 const TLBString
*Name
; /* the name of this variable */
1193 int HelpStringContext
;
1194 const TLBString
*HelpString
;
1195 struct list custdata_list
;
1198 /* internal implemented interface data */
1199 typedef struct tagTLBImplType
1201 HREFTYPE hRef
; /* hRef of interface */
1202 int implflags
; /* IMPLFLAG_*s */
1203 struct list custdata_list
;
1206 /* internal TypeInfo data */
1207 typedef struct tagITypeInfoImpl
1209 ITypeInfo2 ITypeInfo2_iface
;
1210 ITypeComp ITypeComp_iface
;
1211 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1213 BOOL not_attached_to_typelib
;
1218 TYPEDESC
*tdescAlias
;
1220 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1221 int index
; /* index in this typelib; */
1222 HREFTYPE hreftype
; /* hreftype for app object binding */
1223 /* type libs seem to store the doc strings in ascii
1224 * so why should we do it in unicode?
1226 const TLBString
*Name
;
1227 const TLBString
*DocString
;
1228 const TLBString
*DllName
;
1229 const TLBString
*Schema
;
1230 DWORD dwHelpContext
;
1231 DWORD dwHelpStringContext
;
1234 TLBFuncDesc
*funcdescs
;
1237 TLBVarDesc
*vardescs
;
1239 /* Implemented Interfaces */
1240 TLBImplType
*impltypes
;
1242 struct list
*pcustdata_list
;
1243 struct list custdata_list
;
1246 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1248 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1251 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1253 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1256 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1258 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1261 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1263 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1266 static const ITypeInfo2Vtbl tinfvt
;
1267 static const ITypeCompVtbl tcompvt
;
1268 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1270 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1271 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1273 typedef struct tagTLBContext
1275 unsigned int oStart
; /* start of TLB in file */
1276 unsigned int pos
; /* current pos */
1277 unsigned int length
; /* total length */
1278 void *mapping
; /* memory mapping */
1279 MSFT_SegDir
* pTblDir
;
1280 ITypeLibImpl
* pLibInfo
;
1284 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1286 return str
!= NULL
? str
->str
: NULL
;
1289 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1293 return memcmp(left
, str
->str
, len
);
1296 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1298 return guid
!= NULL
? &guid
->guid
: NULL
;
1301 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1303 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1306 static int get_ptr_size(SYSKIND syskind
)
1316 WARN("Unhandled syskind: 0x%x\n", syskind
);
1323 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1324 if (pTD
->vt
& VT_RESERVED
)
1325 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1326 if (pTD
->vt
& VT_BYREF
)
1327 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1328 if (pTD
->vt
& VT_ARRAY
)
1329 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1330 if (pTD
->vt
& VT_VECTOR
)
1331 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1332 switch(pTD
->vt
& VT_TYPEMASK
) {
1333 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1334 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1335 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1336 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1337 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1338 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1339 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1340 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1341 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1342 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1343 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1344 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1345 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1346 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1347 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1348 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1349 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1350 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1351 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1352 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1353 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx", pTD
->hreftype
); break;
1354 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1355 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1356 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1357 dump_TypeDesc(pTD
->lptdesc
, szVarType
+ 7);
1359 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1360 dump_TypeDesc(pTD
->lptdesc
, szVarType
+ 13);
1362 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1363 pTD
->lpadesc
->cDims
); /* FIXME print out sizes */
1364 dump_TypeDesc(&pTD
->lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1367 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1371 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1373 USHORT flags
= edesc
->paramdesc
.wParamFlags
;
1374 dump_TypeDesc(&edesc
->tdesc
,buf
);
1375 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1376 MESSAGE("\t\tu.paramdesc.wParamFlags");
1377 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1378 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1379 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1380 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1381 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1382 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1383 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1384 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1385 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->paramdesc
.pparamdescex
);
1387 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1389 MESSAGE("memid is %#lx\n", funcdesc
->memid
);
1390 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1391 MESSAGE("Param %d:\n",i
);
1392 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1394 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1395 switch (funcdesc
->funckind
) {
1396 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1397 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1398 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1399 case FUNC_STATIC
: MESSAGE("static");break;
1400 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1401 default: MESSAGE("unknown");break;
1403 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1404 switch (funcdesc
->invkind
) {
1405 case INVOKE_FUNC
: MESSAGE("func");break;
1406 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1407 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1408 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1410 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1411 switch (funcdesc
->callconv
) {
1412 case CC_CDECL
: MESSAGE("cdecl");break;
1413 case CC_PASCAL
: MESSAGE("pascal");break;
1414 case CC_STDCALL
: MESSAGE("stdcall");break;
1415 case CC_SYSCALL
: MESSAGE("syscall");break;
1418 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1419 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1420 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1422 MESSAGE("\telemdescFunc (return value type):\n");
1423 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1426 static const char * const typekind_desc
[] =
1439 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1442 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1443 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1444 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1447 dump_FUNCDESC(&(pfd
->funcdesc
));
1449 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1450 if(pfd
->Entry
== NULL
)
1451 MESSAGE("\tentry: (null)\n");
1452 else if(pfd
->Entry
== (void*)-1)
1453 MESSAGE("\tentry: invalid\n");
1454 else if(IS_INTRESOURCE(pfd
->Entry
))
1455 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1457 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1459 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1463 dump_TLBFuncDescOne(pfd
);
1468 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1472 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1478 static void dump_TLBImpLib(const TLBImpLib
*import
)
1480 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1481 debugstr_w(import
->name
));
1482 TRACE_(typelib
)("v%d.%d lcid %#lx offset=%x\n", import
->wVersionMajor
, import
->wVersionMinor
, import
->lcid
, import
->offset
);
1485 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1489 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1491 TRACE_(typelib
)("href:%#lx\n", ref
->reference
);
1492 if(ref
->index
== -1)
1493 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1495 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1497 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1499 TRACE_(typelib
)("in lib\n");
1500 dump_TLBImpLib(ref
->pImpTLInfo
);
1505 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1510 TRACE_(typelib
)("implementing/inheriting interface hRef = %lx implflags %x\n",
1511 impl
->hRef
, impl
->implflags
);
1517 static void dump_DispParms(const DISPPARAMS
* pdp
)
1521 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1523 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1525 TRACE("named args:\n");
1526 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1527 TRACE( "\t0x%lx\n", pdp
->rgdispidNamedArgs
[index
] );
1530 if (pdp
->cArgs
&& pdp
->rgvarg
)
1533 for (index
= 0; index
< pdp
->cArgs
; index
++)
1534 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1538 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1540 TRACE("%p ref %lu\n", pty
, pty
->ref
);
1541 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1542 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1543 TRACE("kind:%s\n", typekind_desc
[pty
->typeattr
.typekind
]);
1544 TRACE("fct:%u var:%u impl:%u\n", pty
->typeattr
.cFuncs
, pty
->typeattr
.cVars
, pty
->typeattr
.cImplTypes
);
1545 TRACE("wTypeFlags: 0x%04x\n", pty
->typeattr
.wTypeFlags
);
1546 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1547 if (pty
->typeattr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1549 dump_TLBFuncDesc(pty
->funcdescs
, pty
->typeattr
.cFuncs
);
1550 dump_TLBVarDesc(pty
->vardescs
, pty
->typeattr
.cVars
);
1551 dump_TLBImplType(pty
->impltypes
, pty
->typeattr
.cImplTypes
);
1554 static void dump_VARDESC(const VARDESC
*v
)
1556 MESSAGE("memid %ld\n",v
->memid
);
1557 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1558 MESSAGE("oInst %ld\n", v
->oInst
);
1559 dump_ELEMDESC(&(v
->elemdescVar
));
1560 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1561 MESSAGE("varkind %d\n",v
->varkind
);
1564 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1566 /* VT_LPWSTR is largest type that, may appear in type description */
1567 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1568 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1569 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1570 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1571 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1572 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1573 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1574 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1577 static void TLB_abort(void)
1582 /* returns the size required for a deep copy of a typedesc into a
1584 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1588 if (alloc_initial_space
)
1589 size
+= sizeof(TYPEDESC
);
1595 size
+= TLB_SizeTypeDesc(tdesc
->lptdesc
, TRUE
);
1598 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->lpadesc
->cDims
]);
1599 size
+= TLB_SizeTypeDesc(&tdesc
->lpadesc
->tdescElem
, FALSE
);
1605 /* deep copy a typedesc into a flat buffer */
1606 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1611 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1620 dest
->lptdesc
= buffer
;
1621 buffer
= TLB_CopyTypeDesc(NULL
, src
->lptdesc
, buffer
);
1624 dest
->lpadesc
= buffer
;
1625 memcpy(dest
->lpadesc
, src
->lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->lpadesc
->cDims
]));
1626 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->lpadesc
->cDims
]);
1627 buffer
= TLB_CopyTypeDesc(&dest
->lpadesc
->tdescElem
, &src
->lpadesc
->tdescElem
, buffer
);
1633 /* free custom data allocated by MSFT_CustData */
1634 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1636 TLBCustData
*cd
, *cdn
;
1637 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1639 list_remove(&cd
->entry
);
1640 VariantClear(&cd
->data
);
1645 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1650 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1651 ret
= SysAllocStringLen(NULL
, len
- 1);
1652 if (!ret
) return ret
;
1653 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1657 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(ITypeInfoImpl
*typeinfo
, MEMBERID memid
)
1661 for (i
= 0; i
< typeinfo
->typeattr
.cFuncs
; ++i
)
1663 if (typeinfo
->funcdescs
[i
].funcdesc
.memid
== memid
)
1664 return &typeinfo
->funcdescs
[i
];
1670 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid_invkind(ITypeInfoImpl
*typeinfo
, MEMBERID memid
, INVOKEKIND invkind
)
1674 for (i
= 0; i
< typeinfo
->typeattr
.cFuncs
; ++i
)
1676 if (typeinfo
->funcdescs
[i
].funcdesc
.memid
== memid
&& typeinfo
->funcdescs
[i
].funcdesc
.invkind
== invkind
)
1677 return &typeinfo
->funcdescs
[i
];
1683 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(ITypeInfoImpl
*typeinfo
, MEMBERID memid
)
1687 for (i
= 0; i
< typeinfo
->typeattr
.cVars
; ++i
)
1689 if (typeinfo
->vardescs
[i
].vardesc
.memid
== memid
)
1690 return &typeinfo
->vardescs
[i
];
1696 static inline TLBVarDesc
*TLB_get_vardesc_by_name(ITypeInfoImpl
*typeinfo
, const OLECHAR
*name
)
1700 for (i
= 0; i
< typeinfo
->typeattr
.cVars
; ++i
)
1702 if (!lstrcmpiW(TLB_get_bstr(typeinfo
->vardescs
[i
].Name
), name
))
1703 return &typeinfo
->vardescs
[i
];
1709 static inline TLBCustData
*TLB_get_custdata_by_guid(const struct list
*custdata_list
, REFGUID guid
)
1711 TLBCustData
*cust_data
;
1712 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1713 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1718 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeLibImpl
*typelib
, const OLECHAR
*name
)
1722 for (i
= 0; i
< typelib
->TypeInfoCount
; ++i
)
1724 if (!lstrcmpiW(TLB_get_bstr(typelib
->typeinfos
[i
]->Name
), name
))
1725 return typelib
->typeinfos
[i
];
1731 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1733 list_init(&var_desc
->custdata_list
);
1736 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1740 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1745 TLBVarDesc_Constructor(&ret
[n
-1]);
1752 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1756 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1761 list_init(&ret
[n
-1].custdata_list
);
1768 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1770 list_init(&func_desc
->custdata_list
);
1773 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1777 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1782 TLBFuncDesc_Constructor(&ret
[n
-1]);
1789 static void TLBImplType_Constructor(TLBImplType
*impl
)
1791 list_init(&impl
->custdata_list
);
1794 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1798 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1803 TLBImplType_Constructor(&ret
[n
-1]);
1810 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1811 const GUID
*new_guid
, HREFTYPE hreftype
)
1815 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1816 if (IsEqualGUID(&guid
->guid
, new_guid
))
1820 guid
= heap_alloc(sizeof(TLBGuid
));
1824 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1825 guid
->hreftype
= hreftype
;
1827 list_add_tail(guid_list
, &guid
->entry
);
1832 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1834 TLBCustData
*cust_data
;
1846 return DISP_E_BADVARTYPE
;
1849 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1852 cust_data
= heap_alloc(sizeof(TLBCustData
));
1854 return E_OUTOFMEMORY
;
1856 cust_data
->guid
= tlbguid
;
1857 VariantInit(&cust_data
->data
);
1859 list_add_tail(custdata_list
, &cust_data
->entry
);
1861 VariantClear(&cust_data
->data
);
1863 return VariantCopy(&cust_data
->data
, var
);
1866 /* Used to update list pointers after list itself was moved. */
1867 static void TLB_relink_custdata(struct list
*custdata_list
)
1869 if (custdata_list
->prev
== custdata_list
->next
)
1870 list_init(custdata_list
);
1873 custdata_list
->prev
->next
= custdata_list
;
1874 custdata_list
->next
->prev
= custdata_list
;
1878 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1885 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1886 if (wcscmp(str
->str
, new_str
) == 0)
1890 str
= heap_alloc(sizeof(TLBString
));
1894 str
->str
= SysAllocString(new_str
);
1900 list_add_tail(string_list
, &str
->entry
);
1905 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1906 ULONG
*size
, WORD
*align
)
1912 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1916 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1918 ITypeInfo_Release(other
);
1923 *size
= attr
->cbSizeInstance
;
1925 *align
= attr
->cbAlignment
;
1927 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1928 ITypeInfo_Release(other
);
1933 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1934 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1936 ULONG i
, sub
, ptr_size
;
1939 ptr_size
= get_ptr_size(sys
);
1978 *size
= sizeof(DATE
);
1981 *size
= sizeof(VARIANT
);
1983 if(sys
== SYS_WIN32
)
1984 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1988 *size
= sizeof(DECIMAL
);
1995 for(i
= 0; i
< tdesc
->lpadesc
->cDims
; ++i
)
1996 *size
+= tdesc
->lpadesc
->rgbounds
[i
].cElements
;
1997 hr
= TLB_size_instance(info
, sys
, &tdesc
->lpadesc
->tdescElem
, &sub
, align
);
2002 case VT_USERDEFINED
:
2003 return TLB_get_size_from_hreftype(info
, tdesc
->hreftype
, size
, align
);
2005 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2019 /**********************************************************************
2021 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2024 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2026 if (where
!= DO_NOT_SEEK
)
2028 where
+= pcx
->oStart
;
2029 if (where
> pcx
->length
)
2032 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
2040 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2042 TRACE_(typelib
)("pos=0x%08x len %#lx, %u, %u, %#lx\n",
2043 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2045 MSFT_Seek(pcx
, where
);
2046 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2047 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2052 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2057 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2058 FromLEDWords(buffer
, ret
);
2063 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2068 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2069 FromLEWords(buffer
, ret
);
2074 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2077 MSFT_GuidEntry entry
;
2080 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2082 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2085 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2087 guid
= heap_alloc(sizeof(TLBGuid
));
2089 guid
->offset
= offs
;
2090 guid
->guid
= entry
.guid
;
2091 guid
->hreftype
= entry
.hreftype
;
2093 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2095 offs
+= sizeof(MSFT_GuidEntry
);
2099 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2103 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2104 if(ret
->offset
== offset
){
2105 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2113 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2115 MSFT_NameIntro niName
;
2119 ERR_(typelib
)("bad offset %d\n", offset
);
2123 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2124 pcx
->pTblDir
->pNametab
.offset
+offset
);
2126 return niName
.hreftype
;
2129 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2132 MSFT_NameIntro intro
;
2134 int offs
= 0, lengthInChars
;
2136 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2140 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2143 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2144 intro
.namelen
&= 0xFF;
2145 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2147 len_piece
= (len_piece
+ 4) & ~0x3;
2151 string
= heap_alloc(len_piece
+ 1);
2152 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2153 string
[intro
.namelen
] = '\0';
2155 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2156 string
, -1, NULL
, 0);
2157 if (!lengthInChars
) {
2159 return E_UNEXPECTED
;
2162 tlbstr
= heap_alloc(sizeof(TLBString
));
2164 tlbstr
->offset
= offs
;
2165 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2166 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2170 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2176 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2180 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2181 if (tlbstr
->offset
== offset
) {
2182 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2190 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2194 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2195 if (tlbstr
->offset
== offset
) {
2196 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2205 * read a value and fill a VARIANT structure
2207 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2211 TRACE_(typelib
)("\n");
2213 if(offset
<0) { /* data are packed in here */
2214 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2215 V_I4(pVar
) = offset
& 0x3ffffff;
2218 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2219 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2220 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2221 switch (V_VT(pVar
)){
2222 case VT_EMPTY
: /* FIXME: is this right? */
2223 case VT_NULL
: /* FIXME: is this right? */
2224 case VT_I2
: /* this should not happen */
2235 case VT_VOID
: /* FIXME: is this right? */
2243 case VT_DECIMAL
: /* FIXME: is this right? */
2246 /* pointer types with known behaviour */
2249 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2251 V_BSTR(pVar
) = NULL
;
2254 ptr
= heap_alloc_zero(size
);
2255 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2256 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, size
, NULL
, 0 );
2257 V_BSTR(pVar
)=SysAllocStringLen(NULL
,len
);
2258 MultiByteToWideChar(CP_ACP
, 0, ptr
, size
, V_BSTR(pVar
), len
);
2263 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2270 case VT_USERDEFINED
:
2276 case VT_STREAMED_OBJECT
:
2277 case VT_STORED_OBJECT
:
2278 case VT_BLOB_OBJECT
:
2283 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2287 if(size
>0) /* (big|small) endian correct? */
2288 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2292 * create a linked list with custom data
2294 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2300 TRACE_(typelib
)("\n");
2302 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2306 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2307 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2308 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2309 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2310 list_add_head(custdata_list
, &pNew
->entry
);
2311 offset
= entry
.next
;
2316 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2319 pTd
->vt
=type
& VT_TYPEMASK
;
2321 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2323 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2326 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2328 return (invkind
== INVOKE_PROPERTYGET
||
2329 invkind
== INVOKE_PROPERTYPUT
||
2330 invkind
== INVOKE_PROPERTYPUTREF
);
2334 MSFT_DoFuncs(TLBContext
* pcx
,
2339 TLBFuncDesc
** pptfd
)
2342 * member information is stored in a data structure at offset
2343 * indicated by the memoffset field of the typeinfo structure
2344 * There are several distinctive parts.
2345 * The first part starts with a field that holds the total length
2346 * of this (first) part excluding this field. Then follow the records,
2347 * for each member there is one record.
2349 * The first entry is always the length of the record (including this
2351 * The rest of the record depends on the type of the member. If there is
2352 * a field indicating the member type (function, variable, interface, etc)
2353 * I have not found it yet. At this time we depend on the information
2354 * in the type info and the usual order how things are stored.
2356 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2359 * Third is an equal sized array with file offsets to the name entry
2362 * The fourth and last (?) part is an array with offsets to the records
2363 * in the first part of this file segment.
2366 int infolen
, nameoffset
, reclength
, i
;
2367 int recoffset
= offset
+ sizeof(INT
);
2369 char *recbuf
= heap_alloc(0xffff);
2370 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2371 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2373 TRACE_(typelib
)("\n");
2375 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2377 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2379 for ( i
= 0; i
< cFuncs
; i
++ )
2383 /* name, eventually add to a hash table */
2384 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2385 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2387 /* read the function information record */
2388 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2390 reclength
&= 0xffff;
2392 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2394 /* size without argument data */
2395 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2396 if (pFuncRec
->FKCCIC
& 0x1000)
2397 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2399 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2400 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2402 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2403 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2405 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2407 if (pFuncRec
->FKCCIC
& 0x2000 )
2409 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2410 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2411 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2414 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2417 ptfd
->Entry
= (TLBString
*)-1;
2419 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2420 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2422 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2423 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2425 /* fill the FuncDesc Structure */
2426 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2427 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2429 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2430 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2431 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2432 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2433 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2434 if (ptfd
->funcdesc
.funckind
== FUNC_DISPATCH
)
2435 ptfd
->funcdesc
.oVft
= 0;
2437 ptfd
->funcdesc
.oVft
= (pFuncRec
->VtableOffset
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
2438 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2440 /* nameoffset is sometimes -1 on the second half of a propget/propput
2441 * pair of functions */
2442 if ((nameoffset
== -1) && (i
> 0) &&
2443 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2444 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2445 ptfd
->Name
= ptfd_prev
->Name
;
2447 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2451 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2453 /* do the parameters/arguments */
2454 if(pFuncRec
->nrargs
)
2457 MSFT_ParameterInfo paraminfo
;
2459 ptfd
->funcdesc
.lprgelemdescParam
=
2460 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2462 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2464 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2465 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2467 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2469 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2475 elemdesc
->paramdesc
.wParamFlags
= paraminfo
.Flags
;
2478 if (paraminfo
.oName
!= -1)
2479 ptfd
->pParamDesc
[j
].Name
=
2480 MSFT_ReadName( pcx
, paraminfo
.oName
);
2481 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2484 if ( (elemdesc
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2485 (pFuncRec
->FKCCIC
& 0x1000) )
2487 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2489 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2491 PARAMDESC
* pParamDesc
= &elemdesc
->paramdesc
;
2493 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2494 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2496 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2500 elemdesc
->paramdesc
.pparamdescex
= NULL
;
2503 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2504 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2505 pFuncRec
->FKCCIC
& 0x80 )
2508 pFuncRec
->oArgCustData
[j
],
2509 &ptfd
->pParamDesc
[j
].custdata_list
);
2512 /* SEEK value = jump to offset,
2513 * from there jump to the end of record,
2514 * go back by (j-1) arguments
2516 MSFT_ReadLEDWords( ¶minfo
,
2517 sizeof(MSFT_ParameterInfo
), pcx
,
2518 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2519 * sizeof(MSFT_ParameterInfo
)));
2523 /* scode is not used: archaic win16 stuff FIXME: right? */
2524 ptfd
->funcdesc
.cScodes
= 0 ;
2525 ptfd
->funcdesc
.lprgscode
= NULL
;
2529 recoffset
+= reclength
;
2534 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2535 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2537 int infolen
, nameoffset
, reclength
;
2539 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2544 TRACE_(typelib
)("\n");
2546 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2547 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2548 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2549 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2550 recoffset
+= offset
+sizeof(INT
);
2551 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2552 /* name, eventually add to a hash table */
2553 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2554 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2555 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2556 /* read the variable information record */
2557 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2559 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2562 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2563 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2565 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2566 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2568 if (reclength
> FIELD_OFFSET(MSFT_VarRecord
, oCustData
))
2569 MSFT_CustData(pcx
, pVarRec
->oCustData
, &ptvd
->custdata_list
);
2571 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2572 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2574 /* fill the VarDesc Structure */
2575 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2576 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2577 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2578 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2579 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2580 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2581 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2582 if(pVarRec
->VarKind
== VAR_CONST
){
2583 ptvd
->vardesc
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2584 MSFT_ReadValue(ptvd
->vardesc
.lpvarValue
,
2585 pVarRec
->OffsValue
, pcx
);
2587 ptvd
->vardesc
.oInst
=pVarRec
->OffsValue
;
2588 recoffset
+= reclength
;
2592 /* process Implemented Interfaces of a com class */
2593 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2597 MSFT_RefRecord refrec
;
2600 TRACE_(typelib
)("\n");
2602 pTI
->impltypes
= TLBImplType_Alloc(count
);
2603 pImpl
= pTI
->impltypes
;
2604 for(i
=0;i
<count
;i
++){
2605 if(offset
<0) break; /* paranoia */
2606 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2607 pImpl
->hRef
= refrec
.reftype
;
2608 pImpl
->implflags
=refrec
.flags
;
2609 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2610 offset
=refrec
.onext
;
2616 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2617 * and some structures, and fix the alignment */
2618 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2620 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2621 switch(info
->tdescAlias
->vt
){
2629 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2630 info
->typeattr
.cbAlignment
= sizeof(void*);
2633 case VT_USERDEFINED
:
2634 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2637 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2638 info
->typeattr
.cbAlignment
= 8;
2640 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2641 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2643 info
->typeattr
.cbAlignment
= sizeof(void*);
2646 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2647 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2648 info
->typeattr
.typekind
== TKIND_COCLASS
){
2649 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2650 info
->typeattr
.cbAlignment
= sizeof(void*);
2656 * process a typeinfo record
2658 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2661 ITypeLibImpl
* pLibInfo
)
2663 MSFT_TypeInfoBase tiBase
;
2664 ITypeInfoImpl
*ptiRet
;
2666 TRACE_(typelib
)("count=%u\n", count
);
2668 ptiRet
= ITypeInfoImpl_Constructor();
2669 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2670 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2672 /* this is where we are coming from */
2673 ptiRet
->pTypeLib
= pLibInfo
;
2674 ptiRet
->index
=count
;
2676 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2677 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2678 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2679 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2680 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2681 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2682 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2683 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2684 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2685 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2686 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2687 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2688 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
;
2689 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2691 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2692 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2693 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2697 /* IDLDESC idldescType; *//* never saw this one != zero */
2699 /* name, eventually add to a hash table */
2700 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2701 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2702 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2704 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2705 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2706 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2708 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2709 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2711 /* note: InfoType's Help file and HelpStringDll come from the containing
2712 * library. Further HelpString and Docstring appear to be the same thing :(
2715 if(ptiRet
->typeattr
.cFuncs
>0 )
2716 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2717 ptiRet
->typeattr
.cVars
,
2718 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2720 if(ptiRet
->typeattr
.cVars
>0 )
2721 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2722 ptiRet
->typeattr
.cVars
,
2723 tiBase
.memoffset
, &ptiRet
->vardescs
);
2724 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2725 switch(ptiRet
->typeattr
.typekind
)
2728 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2731 case TKIND_DISPATCH
:
2732 /* This is not -1 when the interface is a non-base dual interface or
2733 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2734 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2738 if (tiBase
.datatype1
!= -1)
2740 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2741 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2745 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2746 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2750 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2752 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2753 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2754 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2755 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2756 if (TRACE_ON(typelib
))
2757 dump_TypeInfo(ptiRet
);
2762 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2765 INT16 len_str
, len_piece
;
2766 int offs
= 0, lengthInChars
;
2768 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2772 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2775 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2776 len_piece
= len_str
+ sizeof(INT16
);
2778 len_piece
= (len_piece
+ 4) & ~0x3;
2782 string
= heap_alloc(len_piece
+ 1);
2783 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2784 string
[len_str
] = '\0';
2786 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2787 string
, -1, NULL
, 0);
2788 if (!lengthInChars
) {
2790 return E_UNEXPECTED
;
2793 tlbstr
= heap_alloc(sizeof(TLBString
));
2795 tlbstr
->offset
= offs
;
2796 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2797 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2801 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2807 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2812 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2813 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2814 MSFT_ImpInfo impinfo
;
2817 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2819 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2820 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2822 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2823 if(pImpLib
->offset
==impinfo
.oImpFile
)
2826 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2827 ref
->reference
= offs
;
2828 ref
->pImpTLInfo
= pImpLib
;
2829 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2830 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2831 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2832 ref
->index
= TLB_REF_USE_GUID
;
2834 ref
->index
= impinfo
.oGuid
;
2836 ERR("Cannot find a reference\n");
2837 ref
->reference
= -1;
2838 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2841 offs
+= sizeof(impinfo
);
2847 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2848 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2849 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2852 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2853 static CRITICAL_SECTION cache_section
;
2854 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2856 0, 0, &cache_section
,
2857 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2858 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2860 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2863 typedef struct TLB_PEFile
2865 IUnknown IUnknown_iface
;
2868 HRSRC typelib_resource
;
2869 HGLOBAL typelib_global
;
2870 LPVOID typelib_base
;
2873 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2875 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2878 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2880 if (IsEqualIID(riid
, &IID_IUnknown
))
2883 IUnknown_AddRef(iface
);
2887 return E_NOINTERFACE
;
2890 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2892 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2893 return InterlockedIncrement(&This
->refs
);
2896 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2898 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2899 ULONG refs
= InterlockedDecrement(&This
->refs
);
2902 if (This
->typelib_global
)
2903 FreeResource(This
->typelib_global
);
2905 FreeLibrary(This
->dll
);
2911 static const IUnknownVtbl TLB_PEFile_Vtable
=
2913 TLB_PEFile_QueryInterface
,
2918 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2921 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2923 This
= heap_alloc(sizeof(TLB_PEFile
));
2925 return E_OUTOFMEMORY
;
2927 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2930 This
->typelib_resource
= NULL
;
2931 This
->typelib_global
= NULL
;
2932 This
->typelib_base
= NULL
;
2934 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2935 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2939 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), L
"TYPELIB");
2940 if (This
->typelib_resource
)
2942 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2943 if (This
->typelib_global
)
2945 This
->typelib_base
= LockResource(This
->typelib_global
);
2947 if (This
->typelib_base
)
2949 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2950 *ppBase
= This
->typelib_base
;
2951 *ppFile
= &This
->IUnknown_iface
;
2957 TRACE("No TYPELIB resource found\n");
2961 TLB_PEFile_Release(&This
->IUnknown_iface
);
2965 typedef struct TLB_NEFile
2967 IUnknown IUnknown_iface
;
2969 LPVOID typelib_base
;
2972 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2974 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2977 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2979 if (IsEqualIID(riid
, &IID_IUnknown
))
2982 IUnknown_AddRef(iface
);
2986 return E_NOINTERFACE
;
2989 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2991 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2992 return InterlockedIncrement(&This
->refs
);
2995 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2997 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2998 ULONG refs
= InterlockedDecrement(&This
->refs
);
3001 heap_free(This
->typelib_base
);
3007 static const IUnknownVtbl TLB_NEFile_Vtable
=
3009 TLB_NEFile_QueryInterface
,
3014 /***********************************************************************
3015 * read_xx_header [internal]
3017 static int read_xx_header( HFILE lzfd
)
3019 IMAGE_DOS_HEADER mzh
;
3022 LZSeek( lzfd
, 0, SEEK_SET
);
3023 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3025 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3028 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3029 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3032 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3034 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3035 return IMAGE_OS2_SIGNATURE
;
3036 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3037 return IMAGE_NT_SIGNATURE
;
3040 WARN("Can't handle %s files.\n", magic
);
3045 /***********************************************************************
3046 * find_ne_resource [internal]
3048 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3049 DWORD
*resLen
, DWORD
*resOff
)
3051 IMAGE_OS2_HEADER nehd
;
3052 NE_TYPEINFO
*typeInfo
;
3053 NE_NAMEINFO
*nameInfo
;
3059 /* Read in NE header */
3060 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3061 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3063 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3066 TRACE("No resources in NE dll\n" );
3070 /* Read in resource table */
3071 resTab
= heap_alloc( resTabSize
);
3072 if ( !resTab
) return FALSE
;
3074 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3075 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3077 heap_free( resTab
);
3082 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3084 if (!IS_INTRESOURCE(typeid)) /* named type */
3086 BYTE len
= strlen( typeid );
3087 while (typeInfo
->type_id
)
3089 if (!(typeInfo
->type_id
& 0x8000))
3091 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3092 if ((*p
== len
) && !_strnicmp( (char*)p
+1, typeid, len
)) goto found_type
;
3094 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3095 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3098 else /* numeric type id */
3100 WORD id
= LOWORD(typeid) | 0x8000;
3101 while (typeInfo
->type_id
)
3103 if (typeInfo
->type_id
== id
) goto found_type
;
3104 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3105 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3108 TRACE("No typeid entry found for %p\n", typeid );
3109 heap_free( resTab
);
3113 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3115 if (!IS_INTRESOURCE(resid
)) /* named resource */
3117 BYTE len
= strlen( resid
);
3118 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3120 BYTE
*p
= resTab
+ nameInfo
->id
;
3121 if (nameInfo
->id
& 0x8000) continue;
3122 if ((*p
== len
) && !_strnicmp( (char*)p
+1, resid
, len
)) goto found_name
;
3125 else /* numeric resource id */
3127 WORD id
= LOWORD(resid
) | 0x8000;
3128 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3129 if (nameInfo
->id
== id
) goto found_name
;
3131 TRACE("No resid entry found for %p\n", typeid );
3132 heap_free( resTab
);
3136 /* Return resource data */
3137 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3138 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3140 heap_free( resTab
);
3144 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3148 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3151 This
= heap_alloc(sizeof(TLB_NEFile
));
3152 if (!This
) return E_OUTOFMEMORY
;
3154 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3156 This
->typelib_base
= NULL
;
3158 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3159 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3161 DWORD reslen
, offset
;
3162 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3164 This
->typelib_base
= heap_alloc(reslen
);
3165 if( !This
->typelib_base
)
3169 LZSeek( lzfd
, offset
, SEEK_SET
);
3170 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3172 *ppBase
= This
->typelib_base
;
3173 *pdwTLBLength
= reslen
;
3174 *ppFile
= &This
->IUnknown_iface
;
3180 if( lzfd
>= 0) LZClose( lzfd
);
3181 TLB_NEFile_Release(&This
->IUnknown_iface
);
3185 typedef struct TLB_Mapping
3187 IUnknown IUnknown_iface
;
3191 LPVOID typelib_base
;
3194 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3196 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3199 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3201 if (IsEqualIID(riid
, &IID_IUnknown
))
3204 IUnknown_AddRef(iface
);
3208 return E_NOINTERFACE
;
3211 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3213 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3214 return InterlockedIncrement(&This
->refs
);
3217 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3219 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3220 ULONG refs
= InterlockedDecrement(&This
->refs
);
3223 if (This
->typelib_base
)
3224 UnmapViewOfFile(This
->typelib_base
);
3226 CloseHandle(This
->mapping
);
3227 if (This
->file
!= INVALID_HANDLE_VALUE
)
3228 CloseHandle(This
->file
);
3234 static const IUnknownVtbl TLB_Mapping_Vtable
=
3236 TLB_Mapping_QueryInterface
,
3241 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3245 This
= heap_alloc(sizeof(TLB_Mapping
));
3247 return E_OUTOFMEMORY
;
3249 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3251 This
->file
= INVALID_HANDLE_VALUE
;
3252 This
->mapping
= NULL
;
3253 This
->typelib_base
= NULL
;
3255 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3256 if (INVALID_HANDLE_VALUE
!= This
->file
)
3258 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3261 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3262 if(This
->typelib_base
)
3264 /* retrieve file size */
3265 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3266 *ppBase
= This
->typelib_base
;
3267 *ppFile
= &This
->IUnknown_iface
;
3273 IUnknown_Release(&This
->IUnknown_iface
);
3274 return TYPE_E_CANTLOADLIBRARY
;
3277 /****************************************************************************
3280 * find the type of the typelib file and map the typelib resource into
3284 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3285 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3287 ITypeLibImpl
*entry
;
3290 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3291 LPVOID pBase
= NULL
;
3292 DWORD dwTLBLength
= 0;
3293 IUnknown
*pFile
= NULL
;
3298 index_str
= wcsrchr(pszFileName
, '\\');
3299 if(index_str
&& *++index_str
!= '\0')
3302 LONG idx
= wcstol(index_str
, &end_ptr
, 10);
3303 if(*end_ptr
== '\0')
3305 int str_len
= index_str
- pszFileName
- 1;
3307 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3308 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3313 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3315 if(wcschr(file
, '\\'))
3317 lstrcpyW(pszPath
, file
);
3321 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3322 pszPath
[len
] = '\\';
3323 memcpy(pszPath
+ len
+ 1, file
, (lstrlenW(file
) + 1) * sizeof(WCHAR
));
3327 if(file
!= pszFileName
) heap_free(file
);
3329 h
= CreateFileW(pszPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3330 if(h
!= INVALID_HANDLE_VALUE
){
3331 GetFinalPathNameByHandleW(h
, pszPath
, cchPath
, FILE_NAME_NORMALIZED
| VOLUME_NAME_DOS
);
3335 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3337 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3338 EnterCriticalSection(&cache_section
);
3339 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3341 if (!wcsicmp(entry
->path
, pszPath
) && entry
->index
== index
)
3343 TRACE("cache hit\n");
3344 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3345 ITypeLib2_AddRef(*ppTypeLib
);
3346 LeaveCriticalSection(&cache_section
);
3350 LeaveCriticalSection(&cache_section
);
3352 /* now actually load and parse the typelib */
3354 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3355 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3356 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3357 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3358 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3361 if (dwTLBLength
>= 4)
3363 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3364 if (dwSignature
== MSFT_SIGNATURE
)
3365 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3366 else if (dwSignature
== SLTG_SIGNATURE
)
3367 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3370 FIXME("Header type magic %#lx not supported.\n", dwSignature
);
3371 ret
= TYPE_E_CANTLOADLIBRARY
;
3375 ret
= TYPE_E_CANTLOADLIBRARY
;
3376 IUnknown_Release(pFile
);
3380 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3382 TRACE("adding to cache\n");
3383 impl
->path
= heap_alloc((lstrlenW(pszPath
)+1) * sizeof(WCHAR
));
3384 lstrcpyW(impl
->path
, pszPath
);
3385 /* We should really canonicalise the path here. */
3386 impl
->index
= index
;
3388 /* FIXME: check if it has added already in the meantime */
3389 EnterCriticalSection(&cache_section
);
3390 list_add_head(&tlb_cache
, &impl
->entry
);
3391 LeaveCriticalSection(&cache_section
);
3397 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName
), GetLastError());
3399 ret
= TYPE_E_CANTLOADLIBRARY
;
3406 /*================== ITypeLib(2) Methods ===================================*/
3408 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3410 ITypeLibImpl
* pTypeLibImpl
;
3412 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3413 if (!pTypeLibImpl
) return NULL
;
3415 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3416 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3417 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3418 pTypeLibImpl
->ref
= 1;
3420 list_init(&pTypeLibImpl
->implib_list
);
3421 list_init(&pTypeLibImpl
->custdata_list
);
3422 list_init(&pTypeLibImpl
->name_list
);
3423 list_init(&pTypeLibImpl
->string_list
);
3424 list_init(&pTypeLibImpl
->guid_list
);
3425 list_init(&pTypeLibImpl
->ref_list
);
3426 pTypeLibImpl
->dispatch_href
= -1;
3428 return pTypeLibImpl
;
3431 /****************************************************************************
3432 * ITypeLib2_Constructor_MSFT
3434 * loading an MSFT typelib from an in-memory image
3436 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3440 MSFT_Header tlbHeader
;
3441 MSFT_SegDir tlbSegDir
;
3442 ITypeLibImpl
* pTypeLibImpl
;
3445 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
3447 pTypeLibImpl
= TypeLibImpl_Constructor();
3448 if (!pTypeLibImpl
) return NULL
;
3450 /* get pointer to beginning of typelib data */
3454 cx
.pLibInfo
= pTypeLibImpl
;
3455 cx
.length
= dwTLBLength
;
3458 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3459 TRACE_(typelib
)("header:\n");
3460 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3461 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3462 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3465 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3467 /* there is a small amount of information here until the next important
3469 * the segment directory . Try to calculate the amount of data */
3470 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3472 /* now read the segment directory */
3473 TRACE("read segment directory (at %ld)\n",lPSegDir
);
3474 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3475 cx
.pTblDir
= &tlbSegDir
;
3477 /* just check two entries */
3478 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3480 ERR("cannot find the table directory, ptr %#lx\n",lPSegDir
);
3481 heap_free(pTypeLibImpl
);
3485 MSFT_ReadAllNames(&cx
);
3486 MSFT_ReadAllStrings(&cx
);
3487 MSFT_ReadAllGuids(&cx
);
3489 /* now fill our internal data */
3490 /* TLIBATTR fields */
3491 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3493 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3494 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3495 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3496 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3497 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3499 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3500 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3502 /* name, eventually add to a hash table */
3503 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3506 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3507 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3509 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3512 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3513 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3516 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3519 if(tlbHeader
.CustomDataOffset
>= 0)
3521 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3524 /* fill in type descriptions */
3525 if(tlbSegDir
.pTypdescTab
.length
> 0)
3527 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3529 pTypeLibImpl
->ctTypeDesc
= cTD
;
3530 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3531 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3534 /* FIXME: add several sanity checks here */
3535 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3536 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3538 /* FIXME: check safearray */
3540 pTypeLibImpl
->pTypeDesc
[i
].lptdesc
= &std_typedesc
[td
[2]];
3542 pTypeLibImpl
->pTypeDesc
[i
].lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3544 else if(td
[0] == VT_CARRAY
)
3546 /* array descr table here */
3547 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3549 else if(td
[0] == VT_USERDEFINED
)
3551 pTypeLibImpl
->pTypeDesc
[i
].hreftype
= MAKELONG(td
[2],td
[3]);
3553 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3556 /* second time around to fill the array subscript info */
3559 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3560 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3562 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].lpadesc
);
3563 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3566 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3568 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3570 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->cDims
= td
[2];
3572 for(j
= 0; j
<td
[2]; j
++)
3574 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->rgbounds
[j
].cElements
,
3575 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3576 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->rgbounds
[j
].lLbound
,
3577 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3582 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
= NULL
;
3583 ERR("didn't find array description data\n");
3588 /* imported type libs */
3589 if(tlbSegDir
.pImpFiles
.offset
>0)
3592 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3595 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3599 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3600 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3601 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3603 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3604 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3605 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3606 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3609 name
= heap_alloc_zero(size
+1);
3610 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3611 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3614 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3615 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3617 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3621 MSFT_ReadAllRefs(&cx
);
3623 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3626 if(tlbHeader
.nrtypeinfos
>= 0 )
3628 ITypeInfoImpl
**ppTI
;
3630 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3632 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3634 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3637 (pTypeLibImpl
->TypeInfoCount
)++;
3642 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3643 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3644 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3648 TRACE("(%p)\n", pTypeLibImpl
);
3649 return &pTypeLibImpl
->ITypeLib2_iface
;
3653 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3659 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3660 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3664 guid
->Data4
[0] = s
>> 8;
3665 guid
->Data4
[1] = s
& 0xff;
3668 for(i
= 0; i
< 6; i
++) {
3669 memcpy(b
, str
+ 24 + 2 * i
, 2);
3670 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3675 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3682 bytelen
= *(const WORD
*)ptr
;
3683 if(bytelen
== 0xffff) return 2;
3685 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3686 tmp_str
= SysAllocStringLen(NULL
, len
);
3688 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3689 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3690 SysFreeString(tmp_str
);
3695 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3700 bytelen
= *(const WORD
*)ptr
;
3701 if(bytelen
== 0xffff) return 2;
3702 *str
= heap_alloc(bytelen
+ 1);
3703 memcpy(*str
, ptr
+ 2, bytelen
);
3704 (*str
)[bytelen
] = '\0';
3708 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3713 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3714 if (tlbstr
->offset
== offset
)
3718 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3719 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3720 SysFreeString(tmp_str
);
3725 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3727 char *ptr
= pLibBlk
;
3730 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3731 FIXME("libblk magic = %04x\n", w
);
3736 if((w
= *(WORD
*)ptr
) != 0xffff) {
3737 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w
);
3742 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3744 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3746 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3749 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3750 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3753 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3754 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3756 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3759 ptr
+= 4; /* skip res12 */
3761 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3764 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3767 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3770 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3771 ptr
+= sizeof(GUID
);
3773 return ptr
- (char*)pLibBlk
;
3776 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3781 } sltg_ref_lookup_t
;
3783 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3784 HREFTYPE
*typelib_ref
)
3786 if(table
&& typeinfo_ref
< table
->num
)
3788 *typelib_ref
= table
->refs
[typeinfo_ref
];
3792 ERR_(typelib
)("Unable to find reference\n");
3797 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3802 if((*pType
& 0xe00) == 0xe00) {
3804 pTD
->lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3807 switch(*pType
& 0x3f) {
3810 pTD
->lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3814 case VT_USERDEFINED
:
3815 pTD
->vt
= VT_USERDEFINED
;
3816 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->hreftype
);
3822 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3825 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3827 pTD
->vt
= VT_CARRAY
;
3828 pTD
->lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3829 pTD
->lpadesc
->cDims
= pSA
->cDims
;
3830 memcpy(pTD
->lpadesc
->rgbounds
, pSA
->rgsabound
,
3831 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3833 pTD
= &pTD
->lpadesc
->tdescElem
;
3839 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3843 pTD
->vt
= VT_SAFEARRAY
;
3844 pTD
->lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3849 pTD
->vt
= *pType
& 0x3f;
3858 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3859 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3861 /* Handle [in/out] first */
3862 if((*pType
& 0xc000) == 0xc000)
3863 pElem
->paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3864 else if(*pType
& 0x8000)
3865 pElem
->paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3866 else if(*pType
& 0x4000)
3867 pElem
->paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3869 pElem
->paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3872 pElem
->paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3875 pElem
->paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3877 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3881 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3886 TLBRefType
*ref_type
;
3887 sltg_ref_lookup_t
*table
;
3888 HREFTYPE typelib_ref
;
3890 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3891 FIXME("Ref magic = %x\n", pRef
->magic
);
3894 name
= ( (char*)pRef
->names
+ pRef
->number
);
3896 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3897 table
->num
= pRef
->number
>> 3;
3899 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3901 /* We don't want the first href to be 0 */
3902 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3904 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3906 unsigned int lib_offs
, type_num
;
3908 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3910 name
+= SLTG_ReadStringA(name
, &refname
);
3911 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3912 FIXME_(typelib
)("Can't sscanf ref\n");
3913 if(lib_offs
!= 0xffff) {
3916 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3917 if(import
->offset
== lib_offs
)
3920 if(&import
->entry
== &pTL
->implib_list
) {
3921 char fname
[MAX_PATH
+1];
3925 import
= heap_alloc_zero(sizeof(*import
));
3926 import
->offset
= lib_offs
;
3927 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3928 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3929 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
3930 &import
->wVersionMajor
,
3931 &import
->wVersionMinor
,
3932 &import
->lcid
, fname
) != 4) {
3933 FIXME_(typelib
)("can't sscanf ref %s\n",
3934 pNameTable
+ lib_offs
+ 40);
3936 len
= strlen(fname
);
3937 if(fname
[len
-1] != '#')
3938 FIXME("fname = %s\n", fname
);
3939 fname
[len
-1] = '\0';
3940 import
->name
= TLB_MultiByteToBSTR(fname
);
3941 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3943 ref_type
->pImpTLInfo
= import
;
3945 /* Store a reference to IDispatch */
3946 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3947 pTL
->dispatch_href
= typelib_ref
;
3949 } else { /* internal ref */
3950 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3952 ref_type
->reference
= typelib_ref
;
3953 ref_type
->index
= type_num
;
3956 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3958 table
->refs
[ref
] = typelib_ref
;
3961 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3962 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3963 dump_TLBRefType(pTL
);
3967 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3968 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3970 SLTG_ImplInfo
*info
;
3971 TLBImplType
*pImplType
;
3972 /* I don't really get this structure, usually it's 0x16 bytes
3973 long, but iuser.tlb contains some that are 0x18 bytes long.
3974 That's ok because we can use the next ptr to jump to the next
3975 one. But how do we know the length of the last one? The WORD
3976 at offs 0x8 might be the clue. For now I'm just assuming that
3977 the last one is the regular 0x16 bytes. */
3979 info
= (SLTG_ImplInfo
*)pBlk
;
3981 pTI
->typeattr
.cImplTypes
++;
3982 if(info
->next
== 0xffff)
3984 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3987 info
= (SLTG_ImplInfo
*)pBlk
;
3988 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
3989 pImplType
= pTI
->impltypes
;
3991 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3992 pImplType
->implflags
= info
->impltypeflags
;
3995 if(info
->next
== 0xffff)
3998 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3999 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4001 info
++; /* see comment at top of function */
4005 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4006 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4008 TLBVarDesc
*pVarDesc
;
4009 const TLBString
*prevName
= NULL
;
4010 SLTG_Variable
*pItem
;
4014 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4016 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4017 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4019 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4021 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4022 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4023 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4027 if (pItem
->name
== 0xfffe)
4028 pVarDesc
->Name
= prevName
;
4030 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4032 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4033 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4034 TRACE_(typelib
)("memid = %#lx\n", pItem
->memid
);
4036 if(pItem
->flags
& 0x02)
4037 pType
= &pItem
->type
;
4039 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4041 if (pItem
->flags
& ~0xda)
4042 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4044 SLTG_DoElem(pType
, pBlk
,
4045 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4047 if (TRACE_ON(typelib
)) {
4049 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4050 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4053 if (pItem
->flags
& 0x40) {
4054 TRACE_(typelib
)("VAR_DISPATCH\n");
4055 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4057 else if (pItem
->flags
& 0x10) {
4058 TRACE_(typelib
)("VAR_CONST\n");
4059 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4060 pVarDesc
->vardesc
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4061 V_VT(pVarDesc
->vardesc
.lpvarValue
) = VT_INT
;
4062 if (pItem
->flags
& 0x08)
4063 V_INT(pVarDesc
->vardesc
.lpvarValue
) = pItem
->byte_offs
;
4065 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4071 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4073 TRACE_(typelib
)("len = %u\n", len
);
4074 if (len
== 0xffff) {
4077 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4078 str
= SysAllocStringLen(NULL
, alloc_len
);
4079 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4081 V_VT(pVarDesc
->vardesc
.lpvarValue
) = VT_BSTR
;
4082 V_BSTR(pVarDesc
->vardesc
.lpvarValue
) = str
;
4091 V_INT(pVarDesc
->vardesc
.lpvarValue
) =
4092 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4095 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4100 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4101 pVarDesc
->vardesc
.oInst
= pItem
->byte_offs
;
4102 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4105 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4106 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4108 if (pItem
->flags
& 0x80)
4109 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4111 prevName
= pVarDesc
->Name
;
4113 pTI
->typeattr
.cVars
= cVars
;
4116 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4117 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4119 SLTG_Function
*pFunc
;
4121 TLBFuncDesc
*pFuncDesc
;
4123 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4125 pFuncDesc
= pTI
->funcdescs
;
4126 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4127 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4132 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4133 case SLTG_FUNCTION_MAGIC
:
4134 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4136 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4137 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4139 case SLTG_STATIC_FUNCTION_MAGIC
:
4140 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4143 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4146 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4148 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4149 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4150 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4151 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4152 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4153 if (pFuncDesc
->funcdesc
.funckind
== FUNC_DISPATCH
)
4154 pFuncDesc
->funcdesc
.oVft
= 0;
4156 pFuncDesc
->funcdesc
.oVft
= (pFunc
->vtblpos
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
4158 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4159 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4161 if(pFunc
->retnextopt
& 0x80)
4162 pType
= &pFunc
->rettype
;
4164 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4166 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4168 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4169 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4170 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4172 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4174 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4175 char *paramName
= pNameTable
+ *pArg
;
4177 /* If arg type follows then paramName points to the 2nd
4178 letter of the name, else the next WORD is an offset to
4179 the arg type and paramName points to the first letter.
4180 So let's take one char off paramName and see if we're
4181 pointing at an alphanumeric char. However if *pArg is
4182 0xffff or 0xfffe then the param has no name, the former
4183 meaning that the next WORD is the type, the latter
4184 meaning that the next WORD is an offset to the type. */
4189 else if(*pArg
== 0xfffe) {
4193 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4198 if(HaveOffs
) { /* the next word is an offset to type */
4199 pType
= (WORD
*)(pBlk
+ *pArg
);
4200 SLTG_DoElem(pType
, pBlk
,
4201 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4206 pArg
= SLTG_DoElem(pArg
, pBlk
,
4207 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4210 /* Are we an optional param ? */
4211 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4212 pFuncDesc
->funcdesc
.cParamsOpt
)
4213 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4216 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4217 paramName
- pNameTable
, pTI
->pTypeLib
);
4219 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4223 pTI
->typeattr
.cFuncs
= cFuncs
;
4226 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4227 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4228 SLTG_TypeInfoTail
*pTITail
)
4231 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4233 if(pTIHeader
->href_table
!= 0xffffffff) {
4234 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4240 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4241 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4243 heap_free(ref_lookup
);
4247 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4248 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4249 const SLTG_TypeInfoTail
*pTITail
)
4252 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4254 if(pTIHeader
->href_table
!= 0xffffffff) {
4255 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4261 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4262 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4265 if (pTITail
->funcs_off
!= 0xffff)
4266 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4268 heap_free(ref_lookup
);
4270 if (TRACE_ON(typelib
))
4271 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4274 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4275 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4276 const SLTG_TypeInfoTail
*pTITail
)
4278 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4281 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4282 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4283 const SLTG_TypeInfoTail
*pTITail
)
4286 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4288 if (pTITail
->simple_alias
) {
4289 /* if simple alias, no more processing required */
4290 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4291 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4295 if(pTIHeader
->href_table
!= 0xffffffff) {
4296 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4300 /* otherwise it is an offset to a type */
4301 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4303 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4304 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4306 heap_free(ref_lookup
);
4309 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4310 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4311 const SLTG_TypeInfoTail
*pTITail
)
4313 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4314 if (pTIHeader
->href_table
!= 0xffffffff)
4315 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4318 if (pTITail
->vars_off
!= 0xffff)
4319 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4321 if (pTITail
->funcs_off
!= 0xffff)
4322 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4324 if (pTITail
->impls_off
!= 0xffff)
4325 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4327 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4328 * of dispinterface functions including the IDispatch ones, so
4329 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4330 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4332 heap_free(ref_lookup
);
4333 if (TRACE_ON(typelib
))
4334 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4337 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4338 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4339 const SLTG_TypeInfoTail
*pTITail
)
4341 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4344 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4345 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4346 const SLTG_TypeInfoTail
*pTITail
)
4348 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4349 if (pTIHeader
->href_table
!= 0xffffffff)
4350 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4353 if (pTITail
->vars_off
!= 0xffff)
4354 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4356 if (pTITail
->funcs_off
!= 0xffff)
4357 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4358 heap_free(ref_lookup
);
4359 if (TRACE_ON(typelib
))
4363 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4364 manageable copy of it into this */
4377 } SLTG_InternalOtherTypeInfo
;
4379 /****************************************************************************
4380 * ITypeLib2_Constructor_SLTG
4382 * loading a SLTG typelib from an in-memory image
4384 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4386 ITypeLibImpl
*pTypeLibImpl
;
4387 SLTG_Header
*pHeader
;
4388 SLTG_BlkEntry
*pBlkEntry
;
4392 LPVOID pBlk
, pFirstBlk
;
4393 SLTG_LibBlk
*pLibBlk
;
4394 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4395 char *pAfterOTIBlks
= NULL
;
4396 char *pNameTable
, *ptr
;
4399 ITypeInfoImpl
**ppTypeInfoImpl
;
4401 TRACE_(typelib
)("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
4404 pTypeLibImpl
= TypeLibImpl_Constructor();
4405 if (!pTypeLibImpl
) return NULL
;
4409 TRACE_(typelib
)("header:\n");
4410 TRACE_(typelib
)("\tmagic %#lx, file blocks = %d\n", pHeader
->SLTG_magic
,
4411 pHeader
->nrOfFileBlks
);
4412 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
)
4414 FIXME_(typelib
)("Header type magic %#lx not supported.\n", pHeader
->SLTG_magic
);
4418 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4419 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4421 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4422 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4424 /* Next we have a magic block */
4425 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4427 /* Let's see if we're still in sync */
4428 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4429 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4430 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4433 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4434 sizeof(SLTG_DIR_MAGIC
))) {
4435 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4439 pIndex
= (SLTG_Index
*)(pMagic
+1);
4441 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4443 pFirstBlk
= pPad9
+ 1;
4445 /* We'll set up a ptr to the main library block, which is the last one. */
4447 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4448 pBlkEntry
[order
].next
!= 0;
4449 order
= pBlkEntry
[order
].next
- 1) {
4450 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4454 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4456 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4461 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4463 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4466 ptr
= (char*)pLibBlk
+ len
;
4468 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4472 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4474 w
= *(WORD
*)(ptr
+ 2);
4477 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4478 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4479 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4481 w
= *(WORD
*)(ptr
+ 4 + len
);
4483 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4485 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4486 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4487 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4489 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4490 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4491 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4493 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4494 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4497 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4498 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4499 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4500 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4501 len
+= sizeof(SLTG_OtherTypeInfo
);
4505 pAfterOTIBlks
= ptr
;
4507 /* Skip this WORD and get the next DWORD */
4508 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4510 /* Now add this to pLibBLk look at what we're pointing at and
4511 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4512 dust and we should be pointing at the beginning of the name
4515 pNameTable
= (char*)pLibBlk
+ len
;
4517 switch(*(WORD
*)pNameTable
) {
4524 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4528 pNameTable
+= 0x216;
4532 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4534 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4537 /* Hopefully we now have enough ptrs set up to actually read in
4538 some TypeInfos. It's not clear which order to do them in, so
4539 I'll just follow the links along the BlkEntry chain and read
4540 them in the order in which they are in the file */
4542 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4543 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4545 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4546 pBlkEntry
[order
].next
!= 0;
4547 order
= pBlkEntry
[order
].next
- 1, i
++) {
4549 SLTG_TypeInfoHeader
*pTIHeader
;
4550 SLTG_TypeInfoTail
*pTITail
;
4551 SLTG_MemberHeader
*pMemHeader
;
4553 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4554 FIXME_(typelib
)("Index strings don't match\n");
4555 heap_free(pOtherTypeInfoBlks
);
4560 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4561 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4562 heap_free(pOtherTypeInfoBlks
);
4565 TRACE_(typelib
)("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, "
4566 "pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
4567 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4569 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4570 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4571 (*ppTypeInfoImpl
)->index
= i
;
4572 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4573 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4574 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4575 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4576 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4577 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4578 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4579 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4581 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4582 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4584 if((pTIHeader
->typeflags1
& 7) != 2)
4585 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4586 if(pTIHeader
->typeflags3
!= 2)
4587 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4589 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4590 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4591 typekind_desc
[pTIHeader
->typekind
],
4592 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4593 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4595 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4597 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4599 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4600 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4601 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4603 switch(pTIHeader
->typekind
) {
4605 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4606 pTIHeader
, pTITail
);
4610 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4611 pTIHeader
, pTITail
);
4614 case TKIND_INTERFACE
:
4615 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4616 pTIHeader
, pTITail
);
4620 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4621 pTIHeader
, pTITail
);
4625 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4626 pTIHeader
, pTITail
);
4629 case TKIND_DISPATCH
:
4630 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4631 pTIHeader
, pTITail
);
4635 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4636 pTIHeader
, pTITail
);
4640 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4645 /* could get cFuncs, cVars and cImplTypes from here
4646 but we've already set those */
4647 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4663 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4666 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4667 FIXME("Somehow processed %d TypeInfos\n", i
);
4668 heap_free(pOtherTypeInfoBlks
);
4672 heap_free(pOtherTypeInfoBlks
);
4673 return &pTypeLibImpl
->ITypeLib2_iface
;
4676 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4678 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4680 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4682 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4683 IsEqualIID(riid
,&IID_ITypeLib
)||
4684 IsEqualIID(riid
,&IID_ITypeLib2
))
4686 *ppv
= &This
->ITypeLib2_iface
;
4688 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4689 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4691 *ppv
= &This
->ICreateTypeLib2_iface
;
4696 TRACE("-- Interface: E_NOINTERFACE\n");
4697 return E_NOINTERFACE
;
4700 IUnknown_AddRef((IUnknown
*)*ppv
);
4704 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4706 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4707 ULONG ref
= InterlockedIncrement(&This
->ref
);
4709 TRACE("%p, refcount %lu.\n", iface
, ref
);
4714 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4716 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4717 ULONG ref
= InterlockedDecrement(&This
->ref
);
4719 TRACE("%p, refcount %lu.\n", iface
, ref
);
4723 TLBImpLib
*pImpLib
, *pImpLibNext
;
4724 TLBRefType
*ref_type
, *ref_type_next
;
4725 TLBString
*tlbstr
, *tlbstr_next
;
4726 TLBGuid
*tlbguid
, *tlbguid_next
;
4729 /* remove cache entry */
4732 TRACE("removing from cache list\n");
4733 EnterCriticalSection(&cache_section
);
4734 if(This
->entry
.next
)
4735 list_remove(&This
->entry
);
4736 LeaveCriticalSection(&cache_section
);
4737 heap_free(This
->path
);
4739 TRACE(" destroying ITypeLib(%p)\n",This
);
4741 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4742 list_remove(&tlbstr
->entry
);
4743 SysFreeString(tlbstr
->str
);
4747 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4748 list_remove(&tlbstr
->entry
);
4749 SysFreeString(tlbstr
->str
);
4753 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4754 list_remove(&tlbguid
->entry
);
4758 TLB_FreeCustData(&This
->custdata_list
);
4760 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4761 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4762 heap_free(This
->pTypeDesc
[i
].lpadesc
);
4764 heap_free(This
->pTypeDesc
);
4766 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4768 if (pImpLib
->pImpTypeLib
)
4769 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4770 SysFreeString(pImpLib
->name
);
4772 list_remove(&pImpLib
->entry
);
4776 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, ref_type_next
, &This
->ref_list
, TLBRefType
, entry
)
4778 list_remove(&ref_type
->entry
);
4779 heap_free(ref_type
);
4782 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4783 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4784 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4786 heap_free(This
->typeinfos
);
4794 /* ITypeLib::GetTypeInfoCount
4796 * Returns the number of type descriptions in the type library
4798 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4800 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4801 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4802 return This
->TypeInfoCount
;
4805 /* ITypeLib::GetTypeInfo
4807 * retrieves the specified type description in the library.
4809 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4812 ITypeInfo
**ppTInfo
)
4814 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4816 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4819 return E_INVALIDARG
;
4821 if(index
>= This
->TypeInfoCount
)
4822 return TYPE_E_ELEMENTNOTFOUND
;
4824 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4825 ITypeInfo_AddRef(*ppTInfo
);
4831 /* ITypeLibs::GetTypeInfoType
4833 * Retrieves the type of a type description.
4835 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4840 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4842 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4845 return E_INVALIDARG
;
4847 if(index
>= This
->TypeInfoCount
)
4848 return TYPE_E_ELEMENTNOTFOUND
;
4850 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4855 /* ITypeLib::GetTypeInfoOfGuid
4857 * Retrieves the type description that corresponds to the specified GUID.
4860 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4863 ITypeInfo
**ppTInfo
)
4865 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4868 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4870 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4871 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4872 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4873 ITypeInfo_AddRef(*ppTInfo
);
4878 return TYPE_E_ELEMENTNOTFOUND
;
4881 /* ITypeLib::GetLibAttr
4883 * Retrieves the structure that contains the library's attributes.
4886 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4890 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4892 TRACE("(%p, %p)\n", This
, attr
);
4894 if (!attr
) return E_INVALIDARG
;
4896 *attr
= heap_alloc(sizeof(**attr
));
4897 if (!*attr
) return E_OUTOFMEMORY
;
4899 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4900 (*attr
)->lcid
= This
->set_lcid
;
4901 (*attr
)->syskind
= This
->syskind
;
4902 (*attr
)->wMajorVerNum
= This
->ver_major
;
4903 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4904 (*attr
)->wLibFlags
= This
->libflags
;
4909 /* ITypeLib::GetTypeComp
4911 * Enables a client compiler to bind to a library's types, variables,
4912 * constants, and global functions.
4915 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4917 ITypeComp
**ppTComp
)
4919 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4921 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4922 *ppTComp
= &This
->ITypeComp_iface
;
4923 ITypeComp_AddRef(*ppTComp
);
4928 /* ITypeLib::GetDocumentation
4930 * Retrieves the library's documentation string, the complete Help file name
4931 * and path, and the context identifier for the library Help topic in the Help
4934 * On a successful return all non-null BSTR pointers will have been set,
4937 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4941 BSTR
*pBstrDocString
,
4942 DWORD
*pdwHelpContext
,
4943 BSTR
*pBstrHelpFile
)
4945 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4946 HRESULT result
= E_INVALIDARG
;
4949 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4951 pBstrName
, pBstrDocString
,
4952 pdwHelpContext
, pBstrHelpFile
);
4956 /* documentation for the typelib */
4961 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4969 if (This
->DocString
)
4971 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4975 *pBstrDocString
= NULL
;
4979 *pdwHelpContext
= This
->dwHelpContext
;
4985 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
4989 *pBstrHelpFile
= NULL
;
4996 /* for a typeinfo */
4997 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4999 if(SUCCEEDED(result
))
5001 result
= ITypeInfo_GetDocumentation(pTInfo
,
5005 pdwHelpContext
, pBstrHelpFile
);
5007 ITypeInfo_Release(pTInfo
);
5012 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5014 if (pBstrName
) SysFreeString (*pBstrName
);
5016 return STG_E_INSUFFICIENTMEMORY
;
5021 * Indicates whether a passed-in string contains the name of a type or member
5022 * described in the library.
5025 static HRESULT WINAPI
ITypeLib2_fnIsName(
5031 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5033 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5035 TRACE("%p, %s, %#lx, %p.\n", iface
, debugstr_w(szNameBuf
), lHashVal
, pfName
);
5038 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5039 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5040 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5041 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5042 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5044 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5045 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5046 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5047 goto ITypeLib2_fnIsName_exit
;
5050 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5051 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5052 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5058 ITypeLib2_fnIsName_exit
:
5059 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5060 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5065 /* ITypeLib::FindName
5067 * Finds occurrences of a type description in a type library. This may be used
5068 * to quickly verify that a name exists in a type library.
5071 static HRESULT WINAPI
ITypeLib2_fnFindName(
5075 ITypeInfo
**ppTInfo
,
5079 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5084 TRACE("%p, %s %#lx, %p, %p, %p.\n", iface
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5086 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5087 return E_INVALIDARG
;
5089 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5090 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5091 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5095 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5096 memid
[count
] = MEMBERID_NIL
;
5097 goto ITypeLib2_fnFindName_exit
;
5100 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5101 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5103 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5104 memid
[count
] = func
->funcdesc
.memid
;
5105 goto ITypeLib2_fnFindName_exit
;
5109 var
= TLB_get_vardesc_by_name(pTInfo
, name
);
5111 memid
[count
] = var
->vardesc
.memid
;
5112 goto ITypeLib2_fnFindName_exit
;
5116 ITypeLib2_fnFindName_exit
:
5117 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5118 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5121 TRACE("found %d typeinfos\n", count
);
5128 /* ITypeLib::ReleaseTLibAttr
5130 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5133 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5135 TLIBATTR
*pTLibAttr
)
5137 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5138 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5139 heap_free(pTLibAttr
);
5142 /* ITypeLib2::GetCustData
5144 * gets the custom data
5146 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5151 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5152 TLBCustData
*pCData
;
5154 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5156 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5158 return TYPE_E_ELEMENTNOTFOUND
;
5160 VariantInit(pVarVal
);
5161 VariantCopy(pVarVal
, &pCData
->data
);
5166 /* ITypeLib2::GetLibStatistics
5168 * Returns statistics about a type library that are required for efficient
5169 * sizing of hash tables.
5172 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5174 ULONG
*pcUniqueNames
,
5175 ULONG
*pcchUniqueNames
)
5177 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5179 FIXME("(%p): stub!\n", This
);
5181 if(pcUniqueNames
) *pcUniqueNames
=1;
5182 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5186 /* ITypeLib2::GetDocumentation2
5188 * Retrieves the library's documentation string, the complete Help file name
5189 * and path, the localization context to use, and the context ID for the
5190 * library Help topic in the Help file.
5193 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5197 BSTR
*pbstrHelpString
,
5198 DWORD
*pdwHelpStringContext
,
5199 BSTR
*pbstrHelpStringDll
)
5201 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5205 FIXME("%p, %d, %#lx, partially implemented stub!\n", iface
, index
, lcid
);
5207 /* the help string should be obtained from the helpstringdll,
5208 * using the _DLLGetDocumentation function, based on the supplied
5209 * lcid. Nice to do sometime...
5213 /* documentation for the typelib */
5215 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5216 if(pdwHelpStringContext
)
5217 *pdwHelpStringContext
=This
->dwHelpContext
;
5218 if(pbstrHelpStringDll
)
5219 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5225 /* for a typeinfo */
5226 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5228 if(SUCCEEDED(result
))
5230 ITypeInfo2
* pTInfo2
;
5231 result
= ITypeInfo_QueryInterface(pTInfo
,
5233 (LPVOID
*) &pTInfo2
);
5235 if(SUCCEEDED(result
))
5237 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5241 pdwHelpStringContext
,
5242 pbstrHelpStringDll
);
5244 ITypeInfo2_Release(pTInfo2
);
5247 ITypeInfo_Release(pTInfo
);
5253 static HRESULT
TLB_copy_all_custdata(const struct list
*custdata_list
, CUSTDATA
*pCustData
)
5255 TLBCustData
*pCData
;
5260 ct
= list_count(custdata_list
);
5262 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5263 if(!pCustData
->prgCustData
)
5264 return E_OUTOFMEMORY
;
5266 pCustData
->cCustData
= ct
;
5268 cdi
= pCustData
->prgCustData
;
5269 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5270 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5271 VariantInit(&cdi
->varValue
);
5272 hr
= VariantCopy(&cdi
->varValue
, &pCData
->data
);
5273 if(FAILED(hr
)) break;
5281 /* ITypeLib2::GetAllCustData
5283 * Gets all custom data items for the library.
5286 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5288 CUSTDATA
*pCustData
)
5290 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5291 TRACE("(%p)->(%p)\n", This
, pCustData
);
5292 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5295 static const ITypeLib2Vtbl tlbvt
= {
5296 ITypeLib2_fnQueryInterface
,
5298 ITypeLib2_fnRelease
,
5299 ITypeLib2_fnGetTypeInfoCount
,
5300 ITypeLib2_fnGetTypeInfo
,
5301 ITypeLib2_fnGetTypeInfoType
,
5302 ITypeLib2_fnGetTypeInfoOfGuid
,
5303 ITypeLib2_fnGetLibAttr
,
5304 ITypeLib2_fnGetTypeComp
,
5305 ITypeLib2_fnGetDocumentation
,
5307 ITypeLib2_fnFindName
,
5308 ITypeLib2_fnReleaseTLibAttr
,
5310 ITypeLib2_fnGetCustData
,
5311 ITypeLib2_fnGetLibStatistics
,
5312 ITypeLib2_fnGetDocumentation2
,
5313 ITypeLib2_fnGetAllCustData
5317 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5319 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5321 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5324 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5326 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5328 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5331 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5333 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5335 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5338 static HRESULT WINAPI
ITypeLibComp_fnBind(
5343 ITypeInfo
** ppTInfo
,
5344 DESCKIND
* pDescKind
,
5347 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5348 BOOL typemismatch
= FALSE
;
5351 TRACE("%p, %s, %#lx, %#x, %p, %p, %p.\n", iface
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5353 *pDescKind
= DESCKIND_NONE
;
5354 pBindPtr
->lptcomp
= NULL
;
5357 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5358 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5359 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5361 /* FIXME: check wFlags here? */
5362 /* FIXME: we should use a hash table to look this info up using lHash
5363 * instead of an O(n) search */
5364 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5365 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5367 if (pTypeInfo
->Name
&& !wcscmp(pTypeInfo
->Name
->str
, szName
))
5369 *pDescKind
= DESCKIND_TYPECOMP
;
5370 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5371 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5372 TRACE("module or enum: %s\n", debugstr_w(szName
));
5377 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5378 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5380 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5383 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5384 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5386 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5389 else if (hr
== TYPE_E_TYPEMISMATCH
)
5390 typemismatch
= TRUE
;
5393 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5394 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5396 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5398 ITypeInfo
*subtypeinfo
;
5400 DESCKIND subdesckind
;
5402 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5403 &subtypeinfo
, &subdesckind
, &subbindptr
);
5404 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5406 TYPEDESC tdesc_appobject
;
5407 const VARDESC vardesc_appobject
=
5410 NULL
, /* lpstrSchema */
5425 VAR_STATIC
/* varkind */
5428 tdesc_appobject
.hreftype
= pTypeInfo
->hreftype
;
5429 tdesc_appobject
.vt
= VT_USERDEFINED
;
5431 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5433 /* cleanup things filled in by Bind call so we can put our
5434 * application object data in there instead */
5435 switch (subdesckind
)
5437 case DESCKIND_FUNCDESC
:
5438 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5440 case DESCKIND_VARDESC
:
5441 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5446 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5448 if (pTypeInfo
->hreftype
== -1)
5449 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5451 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5455 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5456 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5457 ITypeInfo_AddRef(*ppTInfo
);
5460 else if (hr
== TYPE_E_TYPEMISMATCH
)
5461 typemismatch
= TRUE
;
5467 TRACE("type mismatch %s\n", debugstr_w(szName
));
5468 return TYPE_E_TYPEMISMATCH
;
5472 TRACE("name not found %s\n", debugstr_w(szName
));
5477 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5481 ITypeInfo
** ppTInfo
,
5482 ITypeComp
** ppTComp
)
5484 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5485 ITypeInfoImpl
*info
;
5487 TRACE("%p, %s, %#lx, %p, %p.\n", iface
, debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5489 if(!szName
|| !ppTInfo
|| !ppTComp
)
5490 return E_INVALIDARG
;
5492 info
= TLB_get_typeinfo_by_name(This
, szName
);
5499 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5500 ITypeInfo_AddRef(*ppTInfo
);
5501 *ppTComp
= &info
->ITypeComp_iface
;
5502 ITypeComp_AddRef(*ppTComp
);
5507 static const ITypeCompVtbl tlbtcvt
=
5510 ITypeLibComp_fnQueryInterface
,
5511 ITypeLibComp_fnAddRef
,
5512 ITypeLibComp_fnRelease
,
5514 ITypeLibComp_fnBind
,
5515 ITypeLibComp_fnBindType
5518 /*================== ITypeInfo(2) Methods ===================================*/
5519 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5521 ITypeInfoImpl
*pTypeInfoImpl
;
5523 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5526 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5527 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5528 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5529 pTypeInfoImpl
->ref
= 0;
5530 pTypeInfoImpl
->hreftype
= -1;
5531 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5532 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5533 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5534 list_init(pTypeInfoImpl
->pcustdata_list
);
5536 TRACE("(%p)\n", pTypeInfoImpl
);
5537 return pTypeInfoImpl
;
5540 /* ITypeInfo::QueryInterface
5542 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5547 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5549 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5552 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5553 IsEqualIID(riid
,&IID_ITypeInfo
)||
5554 IsEqualIID(riid
,&IID_ITypeInfo2
))
5555 *ppvObject
= &This
->ITypeInfo2_iface
;
5556 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5557 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5558 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5559 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5560 *ppvObject
= &This
->ITypeComp_iface
;
5563 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5564 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5567 TRACE("-- Interface: E_NOINTERFACE\n");
5568 return E_NOINTERFACE
;
5571 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5573 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5574 ULONG ref
= InterlockedIncrement(&This
->ref
);
5576 TRACE("%p, refcount %lu.\n", iface
, ref
);
5578 if (ref
== 1 /* incremented from 0 */)
5579 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5584 static void typeinfo_release_funcdesc(TLBFuncDesc
*func
)
5588 for (i
= 0; i
< func
->funcdesc
.cParams
; ++i
)
5590 ELEMDESC
*elemdesc
= &func
->funcdesc
.lprgelemdescParam
[i
];
5591 if (elemdesc
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5592 VariantClear(&elemdesc
->paramdesc
.pparamdescex
->varDefaultValue
);
5593 TLB_FreeCustData(&func
->pParamDesc
[i
].custdata_list
);
5595 heap_free(func
->funcdesc
.lprgelemdescParam
);
5596 heap_free(func
->pParamDesc
);
5597 TLB_FreeCustData(&func
->custdata_list
);
5600 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5604 TRACE("destroying ITypeInfo(%p)\n",This
);
5606 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5608 typeinfo_release_funcdesc(&This
->funcdescs
[i
]);
5610 heap_free(This
->funcdescs
);
5612 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5614 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5615 if (pVInfo
->vardesc_create
) {
5616 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5617 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5618 VariantClear(pVInfo
->vardesc
.lpvarValue
);
5619 heap_free(pVInfo
->vardesc
.lpvarValue
);
5621 TLB_FreeCustData(&pVInfo
->custdata_list
);
5623 heap_free(This
->vardescs
);
5625 if(This
->impltypes
){
5626 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5627 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5628 TLB_FreeCustData(&pImpl
->custdata_list
);
5630 heap_free(This
->impltypes
);
5633 TLB_FreeCustData(&This
->custdata_list
);
5638 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5640 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5641 ULONG ref
= InterlockedDecrement(&This
->ref
);
5643 TRACE("%p, refcount %lu.\n", iface
, ref
);
5647 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5648 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5649 if (not_attached_to_typelib
)
5651 /* otherwise This will be freed when typelib is freed */
5657 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5658 LPTYPEATTR
*ppTypeAttr
)
5660 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5663 TRACE("(%p)\n",This
);
5665 size
= sizeof(**ppTypeAttr
);
5666 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5667 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5669 *ppTypeAttr
= heap_alloc(size
);
5671 return E_OUTOFMEMORY
;
5673 **ppTypeAttr
= This
->typeattr
;
5674 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5676 if (This
->tdescAlias
)
5677 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5679 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5680 /* This should include all the inherited funcs */
5681 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5682 /* This is always the size of IDispatch's vtbl */
5683 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5684 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5689 /* ITypeInfo::GetTypeComp
5691 * Retrieves the ITypeComp interface for the type description, which enables a
5692 * client compiler to bind to the type description's members.
5695 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5696 ITypeComp
* *ppTComp
)
5698 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5700 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5702 *ppTComp
= &This
->ITypeComp_iface
;
5703 ITypeComp_AddRef(*ppTComp
);
5707 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5709 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5710 if (elemdesc
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5711 size
+= sizeof(*elemdesc
->paramdesc
.pparamdescex
);
5715 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5718 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5719 if (src
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5721 const PARAMDESCEX
*pparamdescex_src
= src
->paramdesc
.pparamdescex
;
5722 PARAMDESCEX
*pparamdescex_dest
= dest
->paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5723 *buffer
+= sizeof(PARAMDESCEX
);
5724 *pparamdescex_dest
= *pparamdescex_src
;
5725 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5726 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5727 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5728 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5731 dest
->paramdesc
.pparamdescex
= NULL
;
5735 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5737 if (V_VT(var
) == VT_INT
)
5738 return VariantChangeType(var
, var
, 0, VT_I4
);
5739 else if (V_VT(var
) == VT_UINT
)
5740 return VariantChangeType(var
, var
, 0, VT_UI4
);
5745 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5747 if (elemdesc
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5748 VariantClear(&elemdesc
->paramdesc
.pparamdescex
->varDefaultValue
);
5751 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5755 SIZE_T size
= sizeof(*src
);
5759 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5760 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5761 for (i
= 0; i
< src
->cParams
; i
++)
5763 size
+= sizeof(ELEMDESC
);
5764 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5767 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5768 if (!dest
) return E_OUTOFMEMORY
;
5771 if (dispinterface
) /* overwrite funckind */
5772 dest
->funckind
= FUNC_DISPATCH
;
5773 buffer
= (char *)(dest
+ 1);
5775 dest
->oVft
= dest
->oVft
& 0xFFFC;
5777 if (dest
->cScodes
) {
5778 dest
->lprgscode
= (SCODE
*)buffer
;
5779 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5780 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5782 dest
->lprgscode
= NULL
;
5784 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5787 SysFreeString((BSTR
)dest
);
5791 if (dest
->cParams
) {
5792 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5793 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5794 for (i
= 0; i
< src
->cParams
; i
++)
5796 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5802 /* undo the above actions */
5803 for (i
= i
- 1; i
>= 0; i
--)
5804 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5805 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5806 SysFreeString((BSTR
)dest
);
5810 dest
->lprgelemdescParam
= NULL
;
5812 /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
5813 * This accounts for several arguments that are separate in the signature of
5814 * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
5815 if (dispinterface
&& (src
->funckind
!= FUNC_DISPATCH
))
5817 /* functions that have a [retval] parameter return this value into pVarResult.
5818 * [retval] is always the last parameter (if present) */
5819 if (dest
->cParams
&&
5820 (dest
->lprgelemdescParam
[dest
->cParams
- 1].paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5822 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5823 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5825 ERR("elemdesc should have started with VT_PTR instead of:\n");
5827 dump_ELEMDESC(elemdesc
);
5828 return E_UNEXPECTED
;
5831 /* the type pointed to by this [retval] becomes elemdescFunc,
5832 * i.e. the function signature's return type.
5833 * We are using a flat buffer so there is no danger of leaking memory */
5834 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.lptdesc
;
5836 /* remove the last parameter */
5839 else if (dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5840 /* Even if not otherwise replaced HRESULT is returned in pExcepInfo->scode,
5841 * not pVarResult. So the function signature should show no return value. */
5842 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5844 /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
5845 * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
5846 if (dest
->cParams
&& (dest
->lprgelemdescParam
[dest
->cParams
- 1].paramdesc
.wParamFlags
& PARAMFLAG_FLCID
))
5854 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5856 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5857 if (var_desc
->varkind
== VAR_CONST
)
5858 VariantClear(var_desc
->lpvarValue
);
5859 SysFreeString((BSTR
)var_desc
);
5862 /* internal function to make the inherited interfaces' methods appear
5863 * part of the interface */
5864 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5865 UINT index
, const TLBFuncDesc
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5867 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5869 UINT implemented_funcs
= 0;
5874 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5878 ITypeInfo
*pSubTypeInfo
;
5881 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5885 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5888 &sub_funcs
, hrefoffset
);
5889 implemented_funcs
+= sub_funcs
;
5890 ITypeInfo_Release(pSubTypeInfo
);
5893 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5897 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5901 if (index
< implemented_funcs
)
5902 return E_INVALIDARG
;
5903 index
-= implemented_funcs
;
5905 if (index
>= This
->typeattr
.cFuncs
)
5906 return TYPE_E_ELEMENTNOTFOUND
;
5908 *ppFuncDesc
= &This
->funcdescs
[index
];
5912 static HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const TLBFuncDesc
**func_desc
, UINT
*hrefoffset
)
5914 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5916 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5917 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface
, index
, func_desc
, NULL
, hrefoffset
);
5919 if (index
>= This
->typeattr
.cFuncs
)
5920 return TYPE_E_ELEMENTNOTFOUND
;
5922 *func_desc
= &This
->funcdescs
[index
];
5926 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5928 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5931 switch (pTypeDesc
->vt
)
5933 case VT_USERDEFINED
:
5934 pTypeDesc
->hreftype
+= hrefoffset
;
5938 pTypeDesc
= pTypeDesc
->lptdesc
;
5941 pTypeDesc
= &pTypeDesc
->lpadesc
->tdescElem
;
5949 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5952 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5953 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5954 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5957 /* ITypeInfo::GetFuncDesc
5959 * Retrieves the FUNCDESC structure that contains information about a
5960 * specified function.
5963 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5964 LPFUNCDESC
*ppFuncDesc
)
5966 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5967 const TLBFuncDesc
*internal_funcdesc
;
5969 UINT hrefoffset
= 0;
5971 TRACE("(%p) index %d\n", This
, index
);
5974 return E_INVALIDARG
;
5976 if (This
->needs_layout
)
5977 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5979 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5980 &internal_funcdesc
, &hrefoffset
);
5983 WARN("description for function %d not found\n", index
);
5987 hr
= TLB_AllocAndInitFuncDesc(
5988 &internal_funcdesc
->funcdesc
,
5990 This
->typeattr
.typekind
== TKIND_DISPATCH
);
5992 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
5993 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5995 TRACE("-- %#lx.\n", hr
);
5999 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6003 SIZE_T size
= sizeof(*src
);
6006 if (src
->lpstrSchema
) size
+= (lstrlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6007 if (src
->varkind
== VAR_CONST
)
6008 size
+= sizeof(VARIANT
);
6009 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6011 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6012 if (!dest
) return E_OUTOFMEMORY
;
6015 buffer
= (char *)(dest
+ 1);
6016 if (src
->lpstrSchema
)
6019 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6020 len
= lstrlenW(src
->lpstrSchema
);
6021 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6022 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6025 if (src
->varkind
== VAR_CONST
)
6029 dest
->lpvarValue
= (VARIANT
*)buffer
;
6030 *dest
->lpvarValue
= *src
->lpvarValue
;
6031 buffer
+= sizeof(VARIANT
);
6032 VariantInit(dest
->lpvarValue
);
6033 hr
= VariantCopy(dest
->lpvarValue
, src
->lpvarValue
);
6036 SysFreeString((BSTR
)dest
);
6040 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6043 if (src
->varkind
== VAR_CONST
)
6044 VariantClear(dest
->lpvarValue
);
6045 SysFreeString((BSTR
)dest
);
6052 /* ITypeInfo::GetVarDesc
6054 * Retrieves a VARDESC structure that describes the specified variable.
6057 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6058 LPVARDESC
*ppVarDesc
)
6060 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6061 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6063 TRACE("(%p) index %d\n", This
, index
);
6065 if(index
>= This
->typeattr
.cVars
)
6066 return TYPE_E_ELEMENTNOTFOUND
;
6068 if (This
->needs_layout
)
6069 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6071 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6074 /* internal function to make the inherited interfaces' methods appear
6075 * part of the interface, remembering if the top-level was dispinterface */
6076 static HRESULT
typeinfo_getnames( ITypeInfo
*iface
, MEMBERID memid
, BSTR
*names
,
6077 UINT max_names
, UINT
*num_names
, BOOL dispinterface
)
6079 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
6080 const TLBFuncDesc
*func_desc
;
6081 const TLBVarDesc
*var_desc
;
6086 func_desc
= TLB_get_funcdesc_by_memberid(This
, memid
);
6089 UINT params
= func_desc
->funcdesc
.cParams
;
6090 if (!max_names
|| !func_desc
->Name
)
6093 *names
= SysAllocString(TLB_get_bstr(func_desc
->Name
));
6096 if (dispinterface
&& (func_desc
->funcdesc
.funckind
!= FUNC_DISPATCH
))
6098 /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc */
6099 if ((params
> 0) && (func_desc
->funcdesc
.lprgelemdescParam
[params
- 1].paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
6100 --params
; /* Invoke(pVarResult) supplies the [retval] parameter, so it's hidden from DISPPARAMS */
6101 if ((params
> 0) && (func_desc
->funcdesc
.lprgelemdescParam
[params
- 1].paramdesc
.wParamFlags
& PARAMFLAG_FLCID
))
6102 --params
; /* Invoke(lcid) supplies the [lcid] parameter, so it's hidden from DISPPARAMS */
6105 for (i
= 0; i
< params
; i
++)
6107 if (*num_names
>= max_names
|| !func_desc
->pParamDesc
[i
].Name
)
6109 names
[*num_names
] = SysAllocString(TLB_get_bstr(func_desc
->pParamDesc
[i
].Name
));
6115 var_desc
= TLB_get_vardesc_by_memberid(This
, memid
);
6118 *names
= SysAllocString(TLB_get_bstr(var_desc
->Name
));
6123 if (This
->impltypes
&&
6124 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
))
6126 /* recursive search */
6129 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &parent
);
6130 if (SUCCEEDED(result
))
6132 result
= typeinfo_getnames(parent
, memid
, names
, max_names
, num_names
, dispinterface
);
6133 ITypeInfo_Release(parent
);
6136 WARN("Could not search inherited interface!\n");
6140 WARN("no names found\n");
6143 return TYPE_E_ELEMENTNOTFOUND
;
6148 /* ITypeInfo_GetNames
6150 * Retrieves the variable with the specified member ID (or the name of the
6151 * property or method and its parameters) that correspond to the specified
6154 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6155 BSTR
*names
, UINT max_names
, UINT
*num_names
)
6157 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6159 TRACE("%p, %#lx, %p, %d, %p\n", iface
, memid
, names
, max_names
, num_names
);
6161 if (!names
) return E_INVALIDARG
;
6163 return typeinfo_getnames((ITypeInfo
*)iface
, memid
, names
, max_names
, num_names
,
6164 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6167 /* ITypeInfo::GetRefTypeOfImplType
6169 * If a type description describes a COM class, it retrieves the type
6170 * description of the implemented interface types. For an interface,
6171 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6175 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6180 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6183 TRACE("(%p) index %d\n", This
, index
);
6184 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6188 /* only valid on dual interfaces;
6189 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6192 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6198 hr
= TYPE_E_ELEMENTNOTFOUND
;
6201 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6203 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6204 *pRefType
= This
->pTypeLib
->dispatch_href
;
6208 if(index
>= This
->typeattr
.cImplTypes
)
6209 hr
= TYPE_E_ELEMENTNOTFOUND
;
6211 *pRefType
= This
->impltypes
[index
].hRef
;
6212 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6220 TRACE("SUCCESS -- hRef %#lx.\n", *pRefType
);
6222 TRACE("FAILURE -- hresult %#lx.\n", hr
);
6228 /* ITypeInfo::GetImplTypeFlags
6230 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6231 * or base interface in a type description.
6233 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6234 UINT index
, INT
*pImplTypeFlags
)
6236 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6238 TRACE("(%p) index %d\n", This
, index
);
6241 return E_INVALIDARG
;
6243 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6244 *pImplTypeFlags
= 0;
6248 if(index
>= This
->typeattr
.cImplTypes
)
6249 return TYPE_E_ELEMENTNOTFOUND
;
6251 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6257 * Maps between member names and member IDs, and parameter names and
6260 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6261 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6263 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6264 const TLBVarDesc
*pVDesc
;
6268 TRACE("%p, %s, %d.\n", iface
, debugstr_w(*rgszNames
), cNames
);
6270 /* init out parameters in case of failure */
6271 for (i
= 0; i
< cNames
; i
++)
6272 pMemId
[i
] = MEMBERID_NIL
;
6274 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6276 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6277 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6278 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6279 for(i
=1; i
< cNames
; i
++){
6280 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6281 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6283 if( j
<pFDesc
->funcdesc
.cParams
)
6286 ret
=DISP_E_UNKNOWNNAME
;
6288 TRACE("-- %#lx.\n", ret
);
6292 pVDesc
= TLB_get_vardesc_by_name(This
, *rgszNames
);
6295 *pMemId
= pVDesc
->vardesc
.memid
;
6298 /* not found, see if it can be found in an inherited interface */
6299 if(This
->impltypes
) {
6300 /* recursive search */
6302 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6304 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6305 ITypeInfo_Release(pTInfo
);
6308 WARN("Could not search inherited interface!\n");
6310 WARN("no names found\n");
6311 return DISP_E_UNKNOWNNAME
;
6317 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6318 extern double call_double_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6319 __ASM_GLOBAL_FUNC( call_method
,
6321 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6322 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6323 "movl %esp,%ebp\n\t"
6324 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6326 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6328 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6329 "movl 12(%ebp),%edx\n\t"
6330 "movl %esp,%edi\n\t"
6333 "subl %edx,%edi\n\t"
6334 "andl $~15,%edi\n\t"
6335 "movl %edi,%esp\n\t"
6336 "movl 12(%ebp),%ecx\n\t"
6337 "movl 16(%ebp),%esi\n\t"
6340 "1:\tcall *8(%ebp)\n\t"
6341 "subl %esp,%edi\n\t"
6342 "movl 20(%ebp),%ecx\n\t"
6343 "movl %edi,(%ecx)\n\t"
6344 "leal -8(%ebp),%esp\n\t"
6346 __ASM_CFI(".cfi_same_value %edi\n\t")
6348 __ASM_CFI(".cfi_same_value %esi\n\t")
6350 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6351 __ASM_CFI(".cfi_same_value %ebp\n\t")
6353 __ASM_GLOBAL_FUNC( call_double_method
,
6354 "jmp " __ASM_NAME("call_method") )
6356 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6357 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6359 int argspos
= 0, stack_offset
;
6364 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6365 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6366 pvargResult
, V_VT(pvargResult
));
6368 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6370 FIXME("unsupported calling convention %d\n",cc
);
6371 return E_INVALIDARG
;
6374 /* maximum size for an argument is sizeof(VARIANT) */
6375 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6379 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6380 func
= vtable
[oVft
/sizeof(void *)];
6381 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6383 else func
= (void *)oVft
;
6389 args
[argspos
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6392 WARN("invalid return type %u\n", vtReturn
);
6394 return E_INVALIDARG
;
6399 for (i
= 0; i
< cActuals
; i
++)
6401 VARIANT
*arg
= prgpvarg
[i
];
6412 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6413 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6417 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6418 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6420 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6421 args
[argspos
++] = V_BOOL(arg
);
6424 args
[argspos
++] = V_UI4(arg
);
6427 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6435 call_method( func
, argspos
, args
, &stack_offset
);
6438 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6442 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6447 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6450 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6454 if (stack_offset
&& cc
== CC_STDCALL
)
6456 WARN( "stack pointer off by %d\n", stack_offset
);
6457 return DISP_E_BADCALLEE
;
6459 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6460 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6464 #elif defined(__x86_64__)
6466 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6467 extern double CDECL
call_double_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6468 __ASM_GLOBAL_FUNC( call_method
,
6470 __ASM_SEH(".seh_pushreg %rbp\n\t")
6471 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6472 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6473 "movq %rsp,%rbp\n\t"
6474 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6475 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6477 __ASM_SEH(".seh_pushreg %rsi\n\t")
6478 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6480 __ASM_SEH(".seh_pushreg %rdi\n\t")
6481 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6482 __ASM_SEH(".seh_endprologue\n\t")
6483 "movq %rcx,%rax\n\t"
6486 "cmovgq %rdx,%rcx\n\t"
6487 "leaq 0(,%rcx,8),%rdx\n\t"
6488 "subq %rdx,%rsp\n\t"
6489 "andq $~15,%rsp\n\t"
6490 "movq %rsp,%rdi\n\t"
6493 "movq 0(%rsp),%rcx\n\t"
6494 "movq 8(%rsp),%rdx\n\t"
6495 "movq 16(%rsp),%r8\n\t"
6496 "movq 24(%rsp),%r9\n\t"
6497 "movq 0(%rsp),%xmm0\n\t"
6498 "movq 8(%rsp),%xmm1\n\t"
6499 "movq 16(%rsp),%xmm2\n\t"
6500 "movq 24(%rsp),%xmm3\n\t"
6502 "leaq -16(%rbp),%rsp\n\t"
6504 __ASM_CFI(".cfi_same_value %rdi\n\t")
6506 __ASM_CFI(".cfi_same_value %rsi\n\t")
6507 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6509 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6510 __ASM_CFI(".cfi_same_value %rbp\n\t")
6512 __ASM_GLOBAL_FUNC( call_double_method
,
6513 "jmp " __ASM_NAME("call_method") )
6515 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6516 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6523 TRACE("%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d).\n",
6524 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6525 pvargResult
, V_VT(pvargResult
));
6527 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6529 FIXME("unsupported calling convention %d\n",cc
);
6530 return E_INVALIDARG
;
6533 /* maximum size for an argument is sizeof(DWORD_PTR) */
6534 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6538 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6539 func
= vtable
[oVft
/sizeof(void *)];
6540 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6542 else func
= (void *)oVft
;
6548 args
[argspos
++] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6551 WARN("invalid return type %u\n", vtReturn
);
6553 return E_INVALIDARG
;
6558 for (i
= 0; i
< cActuals
; i
++)
6560 VARIANT
*arg
= prgpvarg
[i
];
6566 args
[argspos
++] = (ULONG_PTR
)arg
;
6568 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6569 args
[argspos
++] = V_BOOL(arg
);
6572 args
[argspos
++] = V_UI8(arg
);
6575 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6581 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
);
6585 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
);
6589 call_method( func
, argspos
, args
);
6592 V_UI8(pvargResult
) = call_method( func
, argspos
, args
);
6596 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6597 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6601 #elif defined(__arm__)
6603 extern LONGLONG CDECL
call_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6604 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6605 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6606 __ASM_GLOBAL_FUNC( call_method
,
6609 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6610 * 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)
6613 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6614 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6616 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6617 "beq 1f\n\t" /* Skip allocation if no stack args */
6618 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6619 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6620 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6621 "subs r1, r1, #4\n\t" /* Decrement count */
6622 "bgt 2b\n\t" /* Loop till done */
6626 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6628 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6629 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6631 "blx ip\n\t" /* Call the target function */
6633 "mov sp, fp\n\t" /* Clean the stack using fp */
6634 "pop {fp, pc}\n\t" /* Restore fp and return */
6636 __ASM_GLOBAL_FUNC( call_float_method
,
6637 "b " __ASM_NAME("call_method") )
6638 __ASM_GLOBAL_FUNC( call_double_method
,
6639 "b " __ASM_NAME("call_method") )
6641 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6642 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6657 int rcount
; /* 32-bit register index count */
6659 int scount
= 0; /* single-precision float register index count */
6660 int dcount
= 0; /* double-precision float register index count */
6663 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6664 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6666 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6668 FIXME("unsupported calling convention %d\n",cc
);
6669 return E_INVALIDARG
;
6677 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6678 func
= vtable
[oVft
/sizeof(void *)];
6679 regs
.r
[rcount
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6681 else func
= (void *)oVft
;
6683 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6684 /* first as it will need to be in the 'r' registers: */
6689 regs
.r
[rcount
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6692 WARN("invalid return type %u\n", vtReturn
);
6693 return E_INVALIDARG
;
6694 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6698 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6699 args
= heap_alloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 4 );
6701 for (i
= 0; i
< cActuals
; i
++)
6703 VARIANT
*arg
= prgpvarg
[i
];
6704 DWORD
*pdwarg
= (DWORD
*)(arg
); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6705 int ntemp
; /* Used for counting words split between registers and stack */
6711 case VT_R8
: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6714 dcount
= max( (scount
+ 1) / 2, dcount
);
6717 regs
.sd
.d
[dcount
++] = V_R8(arg
);
6721 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6722 memcpy( &args
[argspos
], &V_R8(arg
), sizeof(V_R8(arg
)) );
6723 argspos
+= sizeof(V_R8(arg
)) / sizeof(DWORD
);
6727 case VT_I8
: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6732 rcount
+= (rcount
% 2); /* align rcount to 8-byte register pair */
6733 memcpy( ®s
.r
[rcount
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6734 rcount
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6738 rcount
= 4; /* Make sure we flag that all 'r' regs are full */
6739 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6740 memcpy( &args
[argspos
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6741 argspos
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6744 case VT_DECIMAL
: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6746 /* 8-byte align 'r' and/or stack: */
6748 rcount
+= (rcount
% 2);
6752 argspos
+= (argspos
% 2);
6754 ntemp
= sizeof(*arg
) / sizeof(DWORD
);
6758 regs
.r
[rcount
++] = *pdwarg
++;
6760 args
[argspos
++] = *pdwarg
++;
6764 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6766 regs
.r
[rcount
++] = V_BOOL(arg
);
6768 args
[argspos
++] = V_BOOL(arg
);
6770 case VT_R4
: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6772 if (!(scount
% 2)) scount
= max( scount
, dcount
* 2 );
6774 regs
.sd
.s
[scount
++] = V_R4(arg
);
6776 args
[argspos
++] = V_UI4(arg
);
6781 regs
.r
[rcount
++] = V_UI4(arg
);
6783 args
[argspos
++] = V_UI4(arg
);
6786 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6789 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 8-byte */
6793 case VT_EMPTY
: /* EMPTY = no return value */
6794 case VT_DECIMAL
: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6796 call_method( func
, argspos
, args
, (DWORD
*)®s
);
6799 V_R4(pvargResult
) = call_float_method( func
, argspos
, args
, (DWORD
*)®s
);
6803 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, (DWORD
*)®s
);
6808 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6811 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6815 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6816 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6820 #elif defined(__aarch64__)
6822 extern DWORD_PTR CDECL
call_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6823 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6824 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6825 __ASM_GLOBAL_FUNC( call_method
,
6826 "stp x29, x30, [sp, #-16]!\n\t"
6828 "sub sp, sp, x1, lsl #3\n\t"
6830 "1:\tsub x1, x1, #1\n\t"
6831 "ldr x4, [x2, x1, lsl #3]\n\t"
6832 "str x4, [sp, x1, lsl #3]\n\t"
6834 "2:\tmov x16, x0\n\t"
6836 "ldp d0, d1, [x9]\n\t"
6837 "ldp d2, d3, [x9, #0x10]\n\t"
6838 "ldp d4, d5, [x9, #0x20]\n\t"
6839 "ldp d6, d7, [x9, #0x30]\n\t"
6840 "ldp x0, x1, [x9, #0x40]\n\t"
6841 "ldp x2, x3, [x9, #0x50]\n\t"
6842 "ldp x4, x5, [x9, #0x60]\n\t"
6843 "ldp x6, x7, [x9, #0x70]\n\t"
6844 "ldr x8, [x9, #0x80]\n\t"
6847 "ldp x29, x30, [sp], #16\n\t"
6849 __ASM_GLOBAL_FUNC( call_float_method
,
6850 "b " __ASM_NAME("call_method") )
6851 __ASM_GLOBAL_FUNC( call_double_method
,
6852 "b " __ASM_NAME("call_method") )
6854 HRESULT WINAPI
DispCallFunc( void *instance
, ULONG_PTR offset
, CALLCONV cc
, VARTYPE ret_type
, UINT count
,
6855 VARTYPE
*types
, VARIANTARG
**vargs
, VARIANT
*result
)
6870 int rcount
; /* 64-bit register index count */
6871 int fpcount
= 0; /* float register index count */
6873 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6874 instance
, offset
, cc
, ret_type
, count
, types
, vargs
, result
, V_VT(result
));
6876 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6878 FIXME("unsupported calling convention %d\n",cc
);
6879 return E_INVALIDARG
;
6887 const FARPROC
*vtable
= *(FARPROC
**)instance
;
6888 func
= vtable
[offset
/sizeof(void *)];
6889 regs
.x
[rcount
++] = (DWORD_PTR
)instance
; /* the This pointer is always the first parameter */
6891 else func
= (void *)offset
;
6893 /* maximum size for an argument is 16 */
6894 args
= heap_alloc( 16 * count
);
6896 for (i
= 0; i
< count
; i
++)
6898 VARIANT
*arg
= vargs
[i
];
6903 if (fpcount
< 8) regs
.fp
[fpcount
++].f
= V_R4(arg
);
6904 else *(float *)&args
[argspos
++] = V_R4(arg
);
6908 if (fpcount
< 8) regs
.fp
[fpcount
++].d
= V_R8(arg
);
6909 else *(double *)&args
[argspos
++] = V_R8(arg
);
6914 memcpy( ®s
.x
[rcount
], arg
, sizeof(*arg
) );
6919 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6924 if (rcount
< 8) regs
.x
[rcount
++] = (DWORD_PTR
)arg
;
6925 else args
[argspos
++] = (DWORD_PTR
)arg
;
6927 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6928 if (rcount
< 8) regs
.x
[rcount
++] = V_BOOL(arg
);
6929 else args
[argspos
++] = V_BOOL(arg
);
6932 if (rcount
< 8) regs
.x
[rcount
++] = V_UI8(arg
);
6933 else args
[argspos
++] = V_UI8(arg
);
6936 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(types
[i
]), debugstr_variant(arg
));
6939 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 16-byte */
6945 return E_INVALIDARG
;
6948 regs
.x
[8] = (DWORD_PTR
)result
; /* x8 is a pointer to the result */
6949 call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6952 V_R4(result
) = call_float_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6956 V_R8(result
) = call_double_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6959 V_UI8(result
) = call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6963 if (ret_type
!= VT_VARIANT
) V_VT(result
) = ret_type
;
6964 TRACE("retval: %s\n", debugstr_variant(result
));
6968 #else /* __aarch64__ */
6970 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6971 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6973 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6974 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6980 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6983 ITypeInfo
*tinfo2
= NULL
;
6984 TYPEATTR
*tattr
= NULL
;
6986 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->hreftype
, &tinfo2
);
6989 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, hr %#lx.\n", tdesc
->hreftype
, hr
);
6992 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6995 ERR("ITypeInfo_GetTypeAttr failed, hr %#lx.\n", hr
);
6996 ITypeInfo_Release(tinfo2
);
7000 switch (tattr
->typekind
)
7007 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
7010 case TKIND_INTERFACE
:
7011 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
7017 case TKIND_DISPATCH
:
7026 FIXME("TKIND_RECORD unhandled.\n");
7031 FIXME("TKIND_UNION unhandled.\n");
7036 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
7040 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7041 ITypeInfo_Release(tinfo2
);
7045 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
7049 /* enforce only one level of pointer indirection */
7050 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
7052 tdesc
= tdesc
->lptdesc
;
7054 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7055 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7056 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7057 if ((tdesc
->vt
== VT_USERDEFINED
) ||
7058 ((tdesc
->vt
== VT_PTR
) && (tdesc
->lptdesc
->vt
== VT_USERDEFINED
)))
7060 VARTYPE vt_userdefined
= 0;
7061 const TYPEDESC
*tdesc_userdefined
= tdesc
;
7062 if (tdesc
->vt
== VT_PTR
)
7064 vt_userdefined
= VT_BYREF
;
7065 tdesc_userdefined
= tdesc
->lptdesc
;
7067 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
7069 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
7070 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
7072 *vt
|= vt_userdefined
;
7084 case VT_USERDEFINED
:
7085 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
7092 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
7093 hr
= DISP_E_BADVARTYPE
;
7097 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->lptdesc
, vt
);
7112 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, HREFTYPE href
, GUID
*guid
)
7119 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
7123 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
7125 ITypeInfo_Release(tinfo2
);
7129 switch(tattr
->typekind
) {
7131 hres
= get_iface_guid(tinfo2
, tattr
->tdescAlias
.hreftype
, guid
);
7134 case TKIND_INTERFACE
:
7135 case TKIND_DISPATCH
:
7136 *guid
= tattr
->guid
;
7140 for (i
= 0; i
< tattr
->cImplTypes
; i
++)
7142 ITypeInfo_GetImplTypeFlags(tinfo2
, i
, &flags
);
7143 if (flags
& IMPLTYPEFLAG_FDEFAULT
)
7147 if (i
== tattr
->cImplTypes
)
7150 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo2
, i
, &href
);
7151 if (SUCCEEDED(hres
))
7152 hres
= get_iface_guid(tinfo2
, href
, guid
);
7156 ERR("Unexpected typekind %d\n", tattr
->typekind
);
7157 hres
= E_UNEXPECTED
;
7160 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7161 ITypeInfo_Release(tinfo2
);
7165 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
7167 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
7170 #define INVBUF_ELEMENT_SIZE \
7171 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7172 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7173 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7174 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7175 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7176 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7177 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7178 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7180 static HRESULT WINAPI
ITypeInfo_fnInvoke(
7185 DISPPARAMS
*pDispParams
,
7186 VARIANT
*pVarResult
,
7187 EXCEPINFO
*pExcepInfo
,
7190 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7192 unsigned int var_index
;
7195 const TLBFuncDesc
*pFuncInfo
;
7198 TRACE("%p, %p, %ld, %#x, %p, %p, %p, %p.\n", iface
, pIUnk
, memid
, wFlags
, pDispParams
,
7199 pVarResult
, pExcepInfo
, pArgErr
);
7201 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7202 return DISP_E_MEMBERNOTFOUND
;
7206 ERR("NULL pDispParams not allowed\n");
7207 return E_INVALIDARG
;
7210 dump_DispParms(pDispParams
);
7212 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7214 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7215 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7216 return E_INVALIDARG
;
7219 /* we do this instead of using GetFuncDesc since it will return a fake
7220 * FUNCDESC for dispinterfaces and we want the real function description */
7221 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7222 pFuncInfo
= &This
->funcdescs
[fdc
];
7223 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7224 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7225 !func_restricted( &pFuncInfo
->funcdesc
))
7229 if (fdc
< This
->typeattr
.cFuncs
) {
7230 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7234 TRACE("invoking:\n");
7235 dump_TLBFuncDescOne(pFuncInfo
);
7238 switch (func_desc
->funckind
) {
7239 case FUNC_PUREVIRTUAL
:
7240 case FUNC_VIRTUAL
: {
7241 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7243 VARIANT retval
= {{{0}}}; /* pointer for storing byref retvals in */
7244 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7245 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7246 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7247 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7248 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7249 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7250 UINT vargs_converted
=0;
7255 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7257 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7259 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7260 hres
= DISP_E_PARAMNOTFOUND
;
7265 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7267 ERR("functions with the vararg attribute do not support named arguments\n");
7268 hres
= DISP_E_NONAMEDARGS
;
7272 for (i
= 0; i
< func_desc
->cParams
; i
++)
7274 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7275 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7280 TRACE("changing args\n");
7281 for (i
= 0; i
< func_desc
->cParams
; i
++)
7283 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
;
7284 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7285 VARIANTARG
*src_arg
;
7287 if (wParamFlags
& PARAMFLAG_FLCID
)
7289 prgpvarg
[i
] = &rgvarg
[i
];
7290 V_VT(prgpvarg
[i
]) = VT_I4
;
7291 V_I4(prgpvarg
[i
]) = This
->pTypeLib
->lcid
;
7297 for (j
= 0; j
< cNamedArgs
; j
++)
7299 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7301 src_arg
= &pDispParams
->rgvarg
[j
];
7306 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7308 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7312 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7314 /* under most conditions the caller is not allowed to
7315 * pass in a dispparam arg in the index of what would be
7316 * the retval parameter. however, there is an exception
7317 * where the extra parameter is used in an extra
7318 * IDispatch::Invoke below */
7319 if ((i
< pDispParams
->cArgs
) &&
7320 ((func_desc
->cParams
!= 1) || !pVarResult
||
7321 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7323 hres
= DISP_E_BADPARAMCOUNT
;
7327 /* note: this check is placed so that if the caller passes
7328 * in a VARIANTARG for the retval we just ignore it, like
7330 if (i
== func_desc
->cParams
- 1)
7332 prgpvarg
[i
] = &rgvarg
[i
];
7333 V_BYREF(prgpvarg
[i
]) = &retval
;
7334 V_VT(prgpvarg
[i
]) = rgvt
[i
];
7338 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7339 hres
= E_UNEXPECTED
;
7343 else if (src_arg
&& !((wParamFlags
& PARAMFLAG_FOPT
) &&
7344 V_VT(src_arg
) == VT_ERROR
&& V_ERROR(src_arg
) == DISP_E_PARAMNOTFOUND
))
7346 TRACE("%s\n", debugstr_variant(src_arg
));
7348 if(rgvt
[i
]!=V_VT(src_arg
))
7350 if (rgvt
[i
] == VT_VARIANT
)
7351 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7352 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7354 if (rgvt
[i
] == V_VT(src_arg
))
7355 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7358 if (wParamFlags
& PARAMFLAG_FIN
)
7359 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7360 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7362 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7364 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7366 SAFEARRAYBOUND bound
;
7370 bound
.cElements
= pDispParams
->cArgs
-i
;
7371 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7373 ERR("SafeArrayCreate failed\n");
7376 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7379 ERR("SafeArrayAccessData failed with %#lx.\n", hres
);
7380 SafeArrayDestroy(a
);
7383 for (j
= 0; j
< bound
.cElements
; j
++)
7384 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7385 hres
= SafeArrayUnaccessData(a
);
7388 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres
);
7389 SafeArrayDestroy(a
);
7392 if (rgvt
[i
] & VT_BYREF
)
7393 V_BYREF(&rgvarg
[i
]) = &a
;
7395 V_ARRAY(&rgvarg
[i
]) = a
;
7396 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7398 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7400 if (wParamFlags
& PARAMFLAG_FIN
)
7401 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7403 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7404 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7405 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7407 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7409 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7410 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7414 /* FIXME: this doesn't work for VT_BYREF arguments if
7415 * they are not the same type as in the paramdesc */
7416 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7417 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7418 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7423 ERR("failed to convert param %d to %s from %s\n", i
,
7424 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7427 prgpvarg
[i
] = &rgvarg
[i
];
7431 prgpvarg
[i
] = src_arg
;
7434 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->lptdesc
->vt
== VT_USERDEFINED
))
7435 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7436 && V_UNKNOWN(prgpvarg
[i
])) {
7437 IUnknown
*userdefined_iface
;
7440 if (tdesc
->vt
== VT_PTR
)
7441 tdesc
= tdesc
->lptdesc
;
7443 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->hreftype
, &guid
);
7447 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7449 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7453 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7454 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7457 else if (wParamFlags
& PARAMFLAG_FOPT
)
7460 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7461 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7463 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].paramdesc
.pparamdescex
->varDefaultValue
);
7469 /* if the function wants a pointer to a variant then
7470 * set that up, otherwise just pass the VT_ERROR in
7471 * the argument by value */
7472 if (rgvt
[i
] & VT_BYREF
)
7474 V_VT(&missing_arg
[i
]) = VT_ERROR
;
7475 V_ERROR(&missing_arg
[i
]) = DISP_E_PARAMNOTFOUND
;
7477 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7478 V_VARIANTREF(arg
) = &missing_arg
[i
];
7482 V_VT(arg
) = VT_ERROR
;
7483 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
7489 hres
= DISP_E_BADPARAMCOUNT
;
7493 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7495 /* VT_VOID is a special case for return types, so it is not
7496 * handled in the general function */
7497 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7498 V_VT(&varresult
) = VT_EMPTY
;
7501 V_VT(&varresult
) = 0;
7502 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7503 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7506 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7507 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7508 prgpvarg
, &varresult
);
7510 vargs_converted
= 0;
7512 for (i
= 0; i
< func_desc
->cParams
; i
++)
7514 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
;
7516 if (wParamFlags
& PARAMFLAG_FLCID
)
7518 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7520 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7524 VariantInit(pVarResult
);
7525 /* deref return value */
7526 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7529 VARIANT_ClearInd(prgpvarg
[i
]);
7531 else if (vargs_converted
< pDispParams
->cArgs
)
7533 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7534 if (wParamFlags
& PARAMFLAG_FOUT
)
7536 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7538 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7542 ERR("failed to convert param %d to vt %d\n", i
,
7543 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7548 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7549 func_desc
->cParamsOpt
< 0 &&
7550 i
== func_desc
->cParams
-1)
7552 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7555 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7558 ERR("SafeArrayGetUBound failed with %#lx.\n", hres
);
7561 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7564 ERR("SafeArrayAccessData failed with %#lx.\n", hres
);
7567 for (j
= 0; j
<= ubound
; j
++)
7568 VariantClear(&v
[j
]);
7569 hres
= SafeArrayUnaccessData(a
);
7572 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres
);
7576 VariantClear(&rgvarg
[i
]);
7579 else if (wParamFlags
& PARAMFLAG_FOPT
)
7581 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7582 VariantClear(&rgvarg
[i
]);
7585 VariantClear(&missing_arg
[i
]);
7588 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7590 WARN("invoked function failed with error %#lx.\n", V_ERROR(&varresult
));
7591 hres
= DISP_E_EXCEPTION
;
7594 IErrorInfo
*pErrorInfo
;
7595 pExcepInfo
->scode
= V_ERROR(&varresult
);
7596 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7598 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7599 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7600 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7601 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7603 IErrorInfo_Release(pErrorInfo
);
7607 if (V_VT(&varresult
) != VT_ERROR
)
7609 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7613 VariantClear(pVarResult
);
7614 *pVarResult
= varresult
;
7617 VariantClear(&varresult
);
7620 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7621 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7622 (func_desc
->lprgelemdescParam
[0].paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7623 (pDispParams
->cArgs
!= 0))
7625 if (V_VT(pVarResult
) == VT_DISPATCH
)
7627 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7628 /* Note: not VariantClear; we still need the dispatch
7629 * pointer to be valid */
7630 VariantInit(pVarResult
);
7631 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7632 GetSystemDefaultLCID(), wFlags
,
7633 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7634 IDispatch_Release(pDispatch
);
7638 VariantClear(pVarResult
);
7639 hres
= DISP_E_NOTACOLLECTION
;
7647 case FUNC_DISPATCH
: {
7650 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7651 if (SUCCEEDED(hres
)) {
7652 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7653 hres
= IDispatch_Invoke(
7654 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7655 pVarResult
,pExcepInfo
,pArgErr
7658 FIXME("IDispatch::Invoke failed with %#lx. (Could be not a real error?)\n", hres
);
7659 IDispatch_Release(disp
);
7661 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7665 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7670 TRACE("-- %#lx\n", hres
);
7673 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7676 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7677 if(FAILED(hres
)) return hres
;
7679 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7680 dump_VARDESC(var_desc
);
7681 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7685 /* not found, look for it in inherited interfaces */
7686 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7687 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7688 if(This
->impltypes
) {
7689 /* recursive search */
7691 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7692 if(SUCCEEDED(hres
)){
7693 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7694 ITypeInfo_Release(pTInfo
);
7697 WARN("Could not search inherited interface!\n");
7700 WARN("did not find member id %ld, flags 0x%x!\n", memid
, wFlags
);
7701 return DISP_E_MEMBERNOTFOUND
;
7704 /* ITypeInfo::GetDocumentation
7706 * Retrieves the documentation string, the complete Help file name and path,
7707 * and the context ID for the Help topic for a specified type description.
7709 * (Can be tested by the Visual Basic Editor in Word for instance.)
7711 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7712 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7713 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7715 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7716 const TLBFuncDesc
*pFDesc
;
7717 const TLBVarDesc
*pVDesc
;
7718 TRACE("%p, %ld, %p, %p, %p, %p.\n",
7719 iface
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7720 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7722 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7724 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7726 *pdwHelpContext
=This
->dwHelpContext
;
7728 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7730 }else {/* for a member */
7731 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
7734 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7736 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7738 *pdwHelpContext
=pFDesc
->helpcontext
;
7740 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7743 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
7746 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7748 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7750 *pdwHelpContext
=pVDesc
->HelpContext
;
7752 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7757 if(This
->impltypes
&&
7758 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7759 /* recursive search */
7762 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7763 if(SUCCEEDED(result
)) {
7764 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7765 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7766 ITypeInfo_Release(pTInfo
);
7769 WARN("Could not search inherited interface!\n");
7772 WARN("member %ld not found\n", memid
);
7773 return TYPE_E_ELEMENTNOTFOUND
;
7776 /* ITypeInfo::GetDllEntry
7778 * Retrieves a description or specification of an entry point for a function
7781 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7782 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7785 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7786 const TLBFuncDesc
*pFDesc
;
7788 TRACE("%p, %#lx, %d, %p, %p, %p.\n", iface
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7790 if (pBstrDllName
) *pBstrDllName
= NULL
;
7791 if (pBstrName
) *pBstrName
= NULL
;
7792 if (pwOrdinal
) *pwOrdinal
= 0;
7794 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7795 return TYPE_E_BADMODULEKIND
;
7797 pFDesc
= TLB_get_funcdesc_by_memberid_invkind(This
, memid
, invKind
);
7798 if (!pFDesc
) return TYPE_E_ELEMENTNOTFOUND
;
7800 dump_TypeInfo(This
);
7801 if (TRACE_ON(ole
)) dump_TLBFuncDescOne(pFDesc
);
7803 if (pBstrDllName
) *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7805 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1))
7807 if (pBstrName
) *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7808 if (pwOrdinal
) *pwOrdinal
= -1;
7812 if (pBstrName
) *pBstrName
= NULL
;
7813 if (pwOrdinal
) *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7818 /* internal function to make the inherited interfaces' methods appear
7819 * part of the interface */
7820 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7821 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7823 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7826 TRACE("%p, %#lx.\n", iface
, *hRefType
);
7828 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7830 ITypeInfo
*pSubTypeInfo
;
7832 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7836 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7838 ITypeInfo_Release(pSubTypeInfo
);
7842 *hRefType
-= DISPATCH_HREF_OFFSET
;
7844 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7845 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7850 /* ITypeInfo::GetRefTypeInfo
7852 * If a type description references other type descriptions, it retrieves
7853 * the referenced type descriptions.
7855 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7858 ITypeInfo
**ppTInfo
)
7860 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7861 ITypeInfo
*type_info
= NULL
;
7862 HRESULT result
= E_FAIL
;
7863 TLBRefType
*ref_type
;
7867 return E_INVALIDARG
;
7869 if ((INT
)hRefType
< 0) {
7870 ITypeInfoImpl
*pTypeInfoImpl
;
7872 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7873 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7874 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7875 return TYPE_E_ELEMENTNOTFOUND
;
7877 /* when we meet a DUAL typeinfo, we must create the alternate
7880 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7882 *pTypeInfoImpl
= *This
;
7883 pTypeInfoImpl
->ref
= 0;
7884 list_init(&pTypeInfoImpl
->custdata_list
);
7886 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7887 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7889 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7891 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7892 /* the AddRef implicitly adds a reference to the parent typelib, which
7893 * stops the copied data from being destroyed until the new typeinfo's
7894 * refcount goes to zero, but we need to signal to the new instance to
7895 * not free its data structures when it is destroyed */
7896 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7897 ITypeInfo_AddRef(*ppTInfo
);
7899 TRACE("got dual interface %p\n", *ppTInfo
);
7903 if ((hRefType
& DISPATCH_HREF_MASK
) && (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7904 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &hRefType
, ppTInfo
);
7906 if(!(hRefType
& 0x1))
7908 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7910 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7913 type_info
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7914 ITypeInfo_AddRef(type_info
);
7922 ITypeLib
*pTLib
= NULL
;
7924 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7926 if(ref_type
->reference
== (hRefType
& (~0x3)))
7929 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7931 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
7935 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7937 TRACE("internal reference\n");
7938 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7940 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7941 TRACE("typeinfo in imported typelib that is already loaded\n");
7942 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7943 ITypeLib_AddRef(pTLib
);
7946 /* Search in cached typelibs */
7947 ITypeLibImpl
*entry
;
7949 EnterCriticalSection(&cache_section
);
7950 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
7953 && IsEqualIID(&entry
->guid
->guid
, TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
))
7954 && entry
->ver_major
== ref_type
->pImpTLInfo
->wVersionMajor
7955 && entry
->ver_minor
== ref_type
->pImpTLInfo
->wVersionMinor
7956 && entry
->set_lcid
== ref_type
->pImpTLInfo
->lcid
7957 && entry
->syskind
== This
->pTypeLib
->syskind
)
7959 TRACE("got cached %p\n", entry
);
7960 pTLib
= (ITypeLib
*)&entry
->ITypeLib2_iface
;
7961 ITypeLib_AddRef(pTLib
);
7966 LeaveCriticalSection(&cache_section
);
7972 /* Search on disk */
7973 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7974 ref_type
->pImpTLInfo
->wVersionMajor
,
7975 ref_type
->pImpTLInfo
->wVersionMinor
,
7976 This
->pTypeLib
->syskind
,
7977 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7979 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7981 result
= LoadTypeLib(libnam
, &pTLib
);
7982 SysFreeString(libnam
);
7985 if(SUCCEEDED(result
)) {
7986 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7987 ITypeLib_AddRef(pTLib
);
7991 if(SUCCEEDED(result
)) {
7992 if(ref_type
->index
== TLB_REF_USE_GUID
)
7993 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), &type_info
);
7995 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, &type_info
);
7998 ITypeLib_Release(pTLib
);
8001 WARN("(%p) failed hreftype %#lx.\n", iface
, hRefType
);
8006 if ((hRefType
& 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info
, -2, ppTInfo
)))
8007 ITypeInfo_Release(type_info
);
8008 else *ppTInfo
= type_info
;
8010 TRACE("%p, hreftype %#lx, loaded %s (%p)\n", iface
, hRefType
,
8011 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
8015 /* ITypeInfo::AddressOfMember
8017 * Retrieves the addresses of static functions or variables, such as those
8020 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
8021 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
8028 TRACE("%p, %lx, %#x, %p.\n", iface
, memid
, invKind
, ppv
);
8030 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
8034 module
= LoadLibraryW(dll
);
8037 ERR("couldn't load %s\n", debugstr_w(dll
));
8039 SysFreeString(entry
);
8040 return STG_E_FILENOTFOUND
;
8042 /* FIXME: store library somewhere where we can free it */
8047 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
8048 entryA
= heap_alloc(len
);
8049 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
8051 *ppv
= GetProcAddress(module
, entryA
);
8053 ERR("function not found %s\n", debugstr_a(entryA
));
8059 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
8061 ERR("function not found %d\n", ordinal
);
8065 SysFreeString(entry
);
8068 return TYPE_E_DLLFUNCTIONNOTFOUND
;
8073 /* ITypeInfo::CreateInstance
8075 * Creates a new instance of a type that describes a component object class
8078 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
8079 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
8081 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8085 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
8091 WARN("Not able to aggregate\n");
8092 return CLASS_E_NOAGGREGATION
;
8095 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
8096 if(FAILED(hr
)) return hr
;
8098 if(pTA
->typekind
!= TKIND_COCLASS
)
8100 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
8106 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
8109 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
8110 TRACE("GetActiveObject rets %#lx.\n", hr
);
8113 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
8114 IUnknown_Release(pUnk
);
8119 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
8120 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8124 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8128 /* ITypeInfo::GetMops
8130 * Retrieves marshalling information.
8132 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
, BSTR
*pBstrMops
)
8134 FIXME("%p, %ld stub!\n", iface
, memid
);
8139 /* ITypeInfo::GetContainingTypeLib
8141 * Retrieves the containing type library and the index of the type description
8142 * within that type library.
8144 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8145 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8147 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8149 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8151 *pIndex
=This
->index
;
8152 TRACE("returning pIndex=%d\n", *pIndex
);
8156 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8157 ITypeLib_AddRef(*ppTLib
);
8158 TRACE("returning ppTLib=%p\n", *ppTLib
);
8164 /* ITypeInfo::ReleaseTypeAttr
8166 * Releases a TYPEATTR previously returned by Get
8169 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8170 TYPEATTR
* pTypeAttr
)
8172 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8173 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8174 heap_free(pTypeAttr
);
8177 /* ITypeInfo::ReleaseFuncDesc
8179 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8181 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8183 FUNCDESC
*pFuncDesc
)
8185 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8188 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8190 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8191 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8192 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8194 SysFreeString((BSTR
)pFuncDesc
);
8197 /* ITypeInfo::ReleaseVarDesc
8199 * Releases a VARDESC previously returned by GetVarDesc.
8201 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8204 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8205 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8207 TLB_FreeVarDesc(pVarDesc
);
8210 /* ITypeInfo2::GetTypeKind
8212 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8215 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8216 TYPEKIND
*pTypeKind
)
8218 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8219 *pTypeKind
= This
->typeattr
.typekind
;
8220 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8224 /* ITypeInfo2::GetTypeFlags
8226 * Returns the type flags without any allocations. This returns a DWORD type
8227 * flag, which expands the type flags without growing the TYPEATTR (type
8231 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8233 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8234 TRACE("%p, %p.\n", iface
, pTypeFlags
);
8235 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8239 /* ITypeInfo2::GetFuncIndexOfMemId
8240 * Binds to a specific member based on a known DISPID, where the member name
8241 * is not known (for example, when binding to a default member).
8244 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8245 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8247 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8251 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8252 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8253 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8256 if(fdc
< This
->typeattr
.cFuncs
) {
8260 result
= TYPE_E_ELEMENTNOTFOUND
;
8262 TRACE("%p, %#lx, %#x, hr %#lx.\n", iface
, memid
, invKind
, result
);
8266 /* TypeInfo2::GetVarIndexOfMemId
8268 * Binds to a specific member based on a known DISPID, where the member name
8269 * is not known (for example, when binding to a default member).
8272 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8273 MEMBERID memid
, UINT
*pVarIndex
)
8275 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8276 TLBVarDesc
*pVarInfo
;
8278 TRACE("%p, %ld, %p.\n", iface
, memid
, pVarIndex
);
8280 pVarInfo
= TLB_get_vardesc_by_memberid(This
, memid
);
8282 return TYPE_E_ELEMENTNOTFOUND
;
8284 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8289 /* ITypeInfo2::GetCustData
8291 * Gets the custom data
8293 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8298 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8299 TLBCustData
*pCData
;
8301 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8303 if(!guid
|| !pVarVal
)
8304 return E_INVALIDARG
;
8306 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8308 VariantInit( pVarVal
);
8310 VariantCopy( pVarVal
, &pCData
->data
);
8312 VariantClear( pVarVal
);
8316 /* ITypeInfo2::GetFuncCustData
8318 * Gets the custom data
8320 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8326 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8327 const TLBFuncDesc
*desc
;
8332 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8334 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &desc
, &hrefoffset
);
8337 WARN("description for function %d not found\n", index
);
8341 VariantInit(pVarVal
);
8342 data
= TLB_get_custdata_by_guid(&desc
->custdata_list
, guid
);
8343 return data
? VariantCopy(pVarVal
, &data
->data
) : S_OK
;
8346 /* ITypeInfo2::GetParamCustData
8348 * Gets the custom data
8350 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8357 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8358 const TLBFuncDesc
*pFDesc
;
8359 TLBCustData
*pCData
;
8363 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8364 debugstr_guid(guid
), pVarVal
);
8366 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8370 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8371 return TYPE_E_ELEMENTNOTFOUND
;
8373 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8375 return TYPE_E_ELEMENTNOTFOUND
;
8377 VariantInit(pVarVal
);
8378 VariantCopy(pVarVal
, &pCData
->data
);
8383 /* ITypeInfo2::GetVarCustData
8385 * Gets the custom data
8387 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8393 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8394 TLBCustData
*pCData
;
8395 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8397 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8399 if(index
>= This
->typeattr
.cVars
)
8400 return TYPE_E_ELEMENTNOTFOUND
;
8402 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8404 return TYPE_E_ELEMENTNOTFOUND
;
8406 VariantInit(pVarVal
);
8407 VariantCopy(pVarVal
, &pCData
->data
);
8412 /* ITypeInfo2::GetImplCustData
8414 * Gets the custom data
8416 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8422 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8423 TLBCustData
*pCData
;
8424 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8426 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8428 if(index
>= This
->typeattr
.cImplTypes
)
8429 return TYPE_E_ELEMENTNOTFOUND
;
8431 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8433 return TYPE_E_ELEMENTNOTFOUND
;
8435 VariantInit(pVarVal
);
8436 VariantCopy(pVarVal
, &pCData
->data
);
8441 /* ITypeInfo2::GetDocumentation2
8443 * Retrieves the documentation string, the complete Help file name and path,
8444 * the localization context to use, and the context ID for the library Help
8445 * topic in the Help file.
8448 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8452 BSTR
*pbstrHelpString
,
8453 DWORD
*pdwHelpStringContext
,
8454 BSTR
*pbstrHelpStringDll
)
8456 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8457 const TLBFuncDesc
*pFDesc
;
8458 const TLBVarDesc
*pVDesc
;
8459 TRACE("%p, %ld, %#lx, %p, %p, %p.\n",
8460 iface
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8461 pbstrHelpStringDll
);
8462 /* the help string should be obtained from the helpstringdll,
8463 * using the _DLLGetDocumentation function, based on the supplied
8464 * lcid. Nice to do sometime...
8466 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8468 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8469 if(pdwHelpStringContext
)
8470 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8471 if(pbstrHelpStringDll
)
8472 *pbstrHelpStringDll
=
8473 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8475 }else {/* for a member */
8476 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
8479 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8480 if(pdwHelpStringContext
)
8481 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8482 if(pbstrHelpStringDll
)
8483 *pbstrHelpStringDll
=
8484 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8487 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
8490 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8491 if(pdwHelpStringContext
)
8492 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8493 if(pbstrHelpStringDll
)
8494 *pbstrHelpStringDll
=
8495 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8499 return TYPE_E_ELEMENTNOTFOUND
;
8502 /* ITypeInfo2::GetAllCustData
8504 * Gets all custom data items for the Type info.
8507 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8509 CUSTDATA
*pCustData
)
8511 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8513 TRACE("%p %p\n", This
, pCustData
);
8515 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8518 /* ITypeInfo2::GetAllFuncCustData
8520 * Gets all custom data items for the specified Function
8523 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8526 CUSTDATA
*pCustData
)
8528 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8529 const TLBFuncDesc
*pFDesc
;
8533 TRACE("%p %u %p\n", This
, index
, pCustData
);
8535 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &pFDesc
, &hrefoffset
);
8539 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8542 /* ITypeInfo2::GetAllParamCustData
8544 * Gets all custom data items for the Functions
8547 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8548 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8550 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8551 const TLBFuncDesc
*pFDesc
;
8555 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8557 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8561 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8562 return TYPE_E_ELEMENTNOTFOUND
;
8564 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8567 /* ITypeInfo2::GetAllVarCustData
8569 * Gets all custom data items for the specified Variable
8572 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8573 UINT index
, CUSTDATA
*pCustData
)
8575 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8576 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8578 TRACE("%p %u %p\n", This
, index
, pCustData
);
8580 if(index
>= This
->typeattr
.cVars
)
8581 return TYPE_E_ELEMENTNOTFOUND
;
8583 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8586 /* ITypeInfo2::GetAllImplCustData
8588 * Gets all custom data items for the specified implementation type
8591 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8594 CUSTDATA
*pCustData
)
8596 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8597 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8599 TRACE("%p %u %p\n", This
, index
, pCustData
);
8601 if(index
>= This
->typeattr
.cImplTypes
)
8602 return TYPE_E_ELEMENTNOTFOUND
;
8604 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8607 static const ITypeInfo2Vtbl tinfvt
=
8610 ITypeInfo_fnQueryInterface
,
8612 ITypeInfo_fnRelease
,
8614 ITypeInfo_fnGetTypeAttr
,
8615 ITypeInfo_fnGetTypeComp
,
8616 ITypeInfo_fnGetFuncDesc
,
8617 ITypeInfo_fnGetVarDesc
,
8618 ITypeInfo_fnGetNames
,
8619 ITypeInfo_fnGetRefTypeOfImplType
,
8620 ITypeInfo_fnGetImplTypeFlags
,
8621 ITypeInfo_fnGetIDsOfNames
,
8623 ITypeInfo_fnGetDocumentation
,
8624 ITypeInfo_fnGetDllEntry
,
8625 ITypeInfo_fnGetRefTypeInfo
,
8626 ITypeInfo_fnAddressOfMember
,
8627 ITypeInfo_fnCreateInstance
,
8628 ITypeInfo_fnGetMops
,
8629 ITypeInfo_fnGetContainingTypeLib
,
8630 ITypeInfo_fnReleaseTypeAttr
,
8631 ITypeInfo_fnReleaseFuncDesc
,
8632 ITypeInfo_fnReleaseVarDesc
,
8634 ITypeInfo2_fnGetTypeKind
,
8635 ITypeInfo2_fnGetTypeFlags
,
8636 ITypeInfo2_fnGetFuncIndexOfMemId
,
8637 ITypeInfo2_fnGetVarIndexOfMemId
,
8638 ITypeInfo2_fnGetCustData
,
8639 ITypeInfo2_fnGetFuncCustData
,
8640 ITypeInfo2_fnGetParamCustData
,
8641 ITypeInfo2_fnGetVarCustData
,
8642 ITypeInfo2_fnGetImplTypeCustData
,
8643 ITypeInfo2_fnGetDocumentation2
,
8644 ITypeInfo2_fnGetAllCustData
,
8645 ITypeInfo2_fnGetAllFuncCustData
,
8646 ITypeInfo2_fnGetAllParamCustData
,
8647 ITypeInfo2_fnGetAllVarCustData
,
8648 ITypeInfo2_fnGetAllImplTypeCustData
,
8651 /******************************************************************************
8652 * CreateDispTypeInfo [OLEAUT32.31]
8654 * Build type information for an object so it can be called through an
8655 * IDispatch interface.
8658 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8659 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8662 * This call allows an objects methods to be accessed through IDispatch, by
8663 * building an ITypeInfo object that IDispatch can use to call through.
8665 HRESULT WINAPI
CreateDispTypeInfo(
8666 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8667 LCID lcid
, /* [I] Locale Id */
8668 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8670 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8671 ITypeLibImpl
*pTypeLibImpl
;
8672 unsigned int param
, func
;
8673 TLBFuncDesc
*pFuncDesc
;
8677 pTypeLibImpl
= TypeLibImpl_Constructor();
8678 if (!pTypeLibImpl
) return E_FAIL
;
8680 pTypeLibImpl
->TypeInfoCount
= 2;
8681 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8683 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8684 pTIIface
->pTypeLib
= pTypeLibImpl
;
8685 pTIIface
->index
= 0;
8686 pTIIface
->Name
= NULL
;
8687 pTIIface
->dwHelpContext
= -1;
8688 pTIIface
->guid
= NULL
;
8689 pTIIface
->typeattr
.lcid
= lcid
;
8690 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8691 pTIIface
->typeattr
.wMajorVerNum
= 0;
8692 pTIIface
->typeattr
.wMinorVerNum
= 0;
8693 pTIIface
->typeattr
.cbAlignment
= 2;
8694 pTIIface
->typeattr
.cbSizeInstance
= -1;
8695 pTIIface
->typeattr
.cbSizeVft
= -1;
8696 pTIIface
->typeattr
.cFuncs
= 0;
8697 pTIIface
->typeattr
.cImplTypes
= 0;
8698 pTIIface
->typeattr
.cVars
= 0;
8699 pTIIface
->typeattr
.wTypeFlags
= 0;
8700 pTIIface
->hreftype
= 0;
8702 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8703 pFuncDesc
= pTIIface
->funcdescs
;
8704 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8705 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8706 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8707 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8708 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8709 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8710 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8711 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8712 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8713 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8714 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8715 pFuncDesc
->funcdesc
.cScodes
= 0;
8716 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8717 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8718 pFuncDesc
->funcdesc
.elemdescFunc
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8719 pFuncDesc
->funcdesc
.elemdescFunc
.paramdesc
.pparamdescex
= NULL
;
8720 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8721 md
->cArgs
* sizeof(ELEMDESC
));
8722 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8723 for(param
= 0; param
< md
->cArgs
; param
++) {
8724 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8725 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8727 pFuncDesc
->helpcontext
= 0;
8728 pFuncDesc
->HelpStringContext
= 0;
8729 pFuncDesc
->HelpString
= NULL
;
8730 pFuncDesc
->Entry
= NULL
;
8731 list_init(&pFuncDesc
->custdata_list
);
8732 pTIIface
->typeattr
.cFuncs
++;
8736 dump_TypeInfo(pTIIface
);
8738 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8739 pTIClass
->pTypeLib
= pTypeLibImpl
;
8740 pTIClass
->index
= 1;
8741 pTIClass
->Name
= NULL
;
8742 pTIClass
->dwHelpContext
= -1;
8743 pTIClass
->guid
= NULL
;
8744 pTIClass
->typeattr
.lcid
= lcid
;
8745 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8746 pTIClass
->typeattr
.wMajorVerNum
= 0;
8747 pTIClass
->typeattr
.wMinorVerNum
= 0;
8748 pTIClass
->typeattr
.cbAlignment
= 2;
8749 pTIClass
->typeattr
.cbSizeInstance
= -1;
8750 pTIClass
->typeattr
.cbSizeVft
= -1;
8751 pTIClass
->typeattr
.cFuncs
= 0;
8752 pTIClass
->typeattr
.cImplTypes
= 1;
8753 pTIClass
->typeattr
.cVars
= 0;
8754 pTIClass
->typeattr
.wTypeFlags
= 0;
8755 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8757 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8759 ref
= heap_alloc_zero(sizeof(*ref
));
8760 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8761 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8763 dump_TypeInfo(pTIClass
);
8765 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8767 ITypeInfo_AddRef(*pptinfo
);
8768 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8774 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8776 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8778 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8781 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8783 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8785 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8788 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8790 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8792 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8795 static HRESULT WINAPI
ITypeComp_fnBind(
8800 ITypeInfo
** ppTInfo
,
8801 DESCKIND
* pDescKind
,
8804 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8805 const TLBFuncDesc
*pFDesc
;
8806 const TLBVarDesc
*pVDesc
;
8807 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8810 TRACE("%p, %s, %#lx, 0x%x, %p, %p, %p.\n", iface
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8812 *pDescKind
= DESCKIND_NONE
;
8813 pBindPtr
->lpfuncdesc
= NULL
;
8816 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8817 pFDesc
= &This
->funcdescs
[fdc
];
8818 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8819 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8822 /* name found, but wrong flags */
8823 hr
= TYPE_E_TYPEMISMATCH
;
8827 if (fdc
< This
->typeattr
.cFuncs
)
8829 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8831 &pBindPtr
->lpfuncdesc
,
8832 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8835 *pDescKind
= DESCKIND_FUNCDESC
;
8836 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8837 ITypeInfo_AddRef(*ppTInfo
);
8840 pVDesc
= TLB_get_vardesc_by_name(This
, szName
);
8842 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8845 *pDescKind
= DESCKIND_VARDESC
;
8846 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8847 ITypeInfo_AddRef(*ppTInfo
);
8852 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8853 /* recursive search */
8857 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8860 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8861 ITypeInfo_Release(pTInfo
);
8865 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8866 ITypeComp_Release(pTComp
);
8867 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8868 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8870 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8871 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8872 SysFreeString((BSTR
)tmp
);
8876 WARN("Could not search inherited interface!\n");
8878 if (hr
== DISP_E_MEMBERNOTFOUND
)
8880 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8884 static HRESULT WINAPI
ITypeComp_fnBindType(
8888 ITypeInfo
** ppTInfo
,
8889 ITypeComp
** ppTComp
)
8891 TRACE("%s, %#lx, %p, %p.\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8893 /* strange behaviour (does nothing) but like the
8896 if (!ppTInfo
|| !ppTComp
)
8905 static const ITypeCompVtbl tcompvt
=
8908 ITypeComp_fnQueryInterface
,
8910 ITypeComp_fnRelease
,
8913 ITypeComp_fnBindType
8916 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8917 ICreateTypeLib2
** ppctlib
)
8922 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8924 if (!szFile
) return E_INVALIDARG
;
8926 This
= TypeLibImpl_Constructor();
8928 return E_OUTOFMEMORY
;
8930 This
->lcid
= GetSystemDefaultLCID();
8931 This
->syskind
= syskind
;
8932 This
->ptr_size
= get_ptr_size(syskind
);
8934 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8936 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8937 return E_OUTOFMEMORY
;
8939 lstrcpyW(This
->path
, szFile
);
8941 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8942 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8946 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8947 REFIID riid
, void **object
)
8949 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8951 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8954 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8956 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8958 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8961 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8963 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8965 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8968 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8969 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8971 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8972 ITypeInfoImpl
*info
;
8975 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8977 if (!ctinfo
|| !name
)
8978 return E_INVALIDARG
;
8980 info
= TLB_get_typeinfo_by_name(This
, name
);
8982 return TYPE_E_NAMECONFLICT
;
8984 if (This
->typeinfos
)
8985 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8986 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8988 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8990 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8992 info
->pTypeLib
= This
;
8993 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8994 info
->index
= This
->TypeInfoCount
;
8995 info
->typeattr
.typekind
= kind
;
8996 info
->typeattr
.cbAlignment
= 4;
8998 switch (info
->typeattr
.typekind
) {
9000 case TKIND_INTERFACE
:
9001 case TKIND_DISPATCH
:
9003 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
9007 info
->typeattr
.cbSizeInstance
= 0;
9010 info
->typeattr
.cbSizeInstance
= 2;
9013 info
->typeattr
.cbSizeInstance
= -0x75;
9016 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
9017 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
9021 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
9022 &IID_ICreateTypeInfo
, (void **)ctinfo
);
9024 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
9028 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
9030 ++This
->TypeInfoCount
;
9035 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
9038 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9040 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
9043 return E_INVALIDARG
;
9045 This
->Name
= TLB_append_str(&This
->name_list
, name
);
9050 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
9051 WORD majorVerNum
, WORD minorVerNum
)
9053 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9055 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
9057 This
->ver_major
= majorVerNum
;
9058 This
->ver_minor
= minorVerNum
;
9063 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
9066 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9068 TRACE("%p %s\n", This
, debugstr_guid(guid
));
9070 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
9075 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
9078 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9080 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
9083 return E_INVALIDARG
;
9085 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
9090 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
9091 LPOLESTR helpFileName
)
9093 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9095 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
9098 return E_INVALIDARG
;
9100 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
9105 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
9108 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9110 TRACE("%p, %ld.\n", iface
, helpContext
);
9112 This
->dwHelpContext
= helpContext
;
9117 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
9120 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9122 TRACE("%p, %#lx.\n", iface
, lcid
);
9124 This
->set_lcid
= lcid
;
9129 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9132 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9134 TRACE("%p %x\n", This
, libFlags
);
9136 This
->libflags
= libFlags
;
9141 typedef struct tagWMSFT_SegContents
{
9144 } WMSFT_SegContents
;
9146 typedef struct tagWMSFT_TLBFile
{
9148 WMSFT_SegContents typeinfo_seg
;
9149 WMSFT_SegContents impfile_seg
;
9150 WMSFT_SegContents impinfo_seg
;
9151 WMSFT_SegContents ref_seg
;
9152 WMSFT_SegContents guidhash_seg
;
9153 WMSFT_SegContents guid_seg
;
9154 WMSFT_SegContents namehash_seg
;
9155 WMSFT_SegContents name_seg
;
9156 WMSFT_SegContents string_seg
;
9157 WMSFT_SegContents typdesc_seg
;
9158 WMSFT_SegContents arraydesc_seg
;
9159 WMSFT_SegContents custdata_seg
;
9160 WMSFT_SegContents cdguids_seg
;
9162 WMSFT_SegContents aux_seg
;
9165 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9166 WMSFT_TLBFile
*file
)
9172 file
->string_seg
.len
= 0;
9173 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9176 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9178 return E_UNEXPECTED
;
9180 size
+= sizeof(INT16
);
9182 size
= (size
+ 4) & ~0x3;
9186 file
->string_seg
.len
+= size
;
9188 /* temporarily use str->offset to store the length of the aligned,
9189 * converted string */
9193 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
9196 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9199 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9200 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9202 heap_free(file
->string_seg
.data
);
9203 return E_UNEXPECTED
;
9206 *((INT16
*)data
) = size
;
9208 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9212 str
->offset
= last_offs
;
9219 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9220 WMSFT_TLBFile
*file
)
9225 MSFT_NameIntro
*last_intro
= NULL
;
9227 file
->header
.nametablecount
= 0;
9228 file
->header
.nametablechars
= 0;
9230 file
->name_seg
.len
= 0;
9231 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9234 size
= lstrlenW(str
->str
);
9235 file
->header
.nametablechars
+= size
;
9236 file
->header
.nametablecount
++;
9238 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9240 return E_UNEXPECTED
;
9242 size
+= sizeof(MSFT_NameIntro
);
9244 size
= (size
+ 4) & ~0x3;
9248 file
->name_seg
.len
+= size
;
9250 /* temporarily use str->offset to store the length of the aligned,
9251 * converted string */
9255 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9256 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
9259 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9261 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9263 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9264 data
+ sizeof(MSFT_NameIntro
),
9265 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9267 heap_free(file
->name_seg
.data
);
9268 return E_UNEXPECTED
;
9270 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9272 intro
->hreftype
= -1; /* TODO? */
9273 intro
->namelen
= size
& 0xFF;
9274 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9275 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9276 intro
->namelen
|= hash
<< 16;
9277 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9278 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9280 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9281 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9283 /* update str->offset to actual value to use in other
9284 * compilation functions that require positions within
9285 * the string table */
9289 str
->offset
= last_offs
;
9294 last_intro
->hreftype
= 0; /* last one is 0? */
9299 static inline int hash_guid(GUID
*guid
)
9303 for (i
= 0; i
< 8; i
++)
9304 hash
^= ((const short *)guid
)[i
];
9309 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9312 MSFT_GuidEntry
*entry
;
9314 int hash_key
, *guidhashtab
;
9316 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9317 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9319 entry
= file
->guid_seg
.data
;
9321 guidhashtab
= file
->guidhash_seg
.data
;
9322 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9323 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9324 entry
->hreftype
= guid
->hreftype
;
9326 hash_key
= hash_guid(&guid
->guid
);
9327 entry
->next_hash
= guidhashtab
[hash_key
];
9328 guidhashtab
[hash_key
] = offs
;
9330 guid
->offset
= offs
;
9331 offs
+= sizeof(MSFT_GuidEntry
);
9338 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9341 VARTYPE arg_type
= V_VT(value
);
9344 DWORD ret
= file
->custdata_seg
.len
;
9346 if(arg_type
== VT_INT
)
9348 if(arg_type
== VT_UINT
)
9352 if(V_VT(value
) != arg_type
) {
9353 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9355 ERR("VariantChangeType failed: %#lx.\n", hres
);
9360 /* Check if default value can be stored in-place */
9365 if(V_UI4(&v
) > 0x3ffffff)
9378 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9381 /* have to allocate space in custdata_seg */
9390 /* Construct the data to be allocated */
9393 if(file
->custdata_seg
.data
){
9394 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9395 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9396 file
->custdata_seg
.len
+= sizeof(int) * 2;
9398 file
->custdata_seg
.len
= sizeof(int) * 2;
9399 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9402 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9403 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9405 /* TODO: Check if the encoded data is already present in custdata_seg */
9411 int mb_len
= WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), NULL
, 0, NULL
, NULL
);
9412 int i
, len
= (6 + mb_len
+ 3) & ~0x3;
9415 if(file
->custdata_seg
.data
){
9416 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9417 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9418 file
->custdata_seg
.len
+= len
;
9420 file
->custdata_seg
.len
= len
;
9421 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9424 *((unsigned short *)data
) = V_VT(value
);
9425 *((unsigned int *)(data
+2)) = mb_len
;
9426 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], mb_len
, NULL
, NULL
);
9427 for (i
= 6 + mb_len
; i
< len
; i
++)
9430 /* TODO: Check if the encoded data is already present in custdata_seg */
9435 FIXME("Argument type not yet handled\n");
9440 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9442 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9444 DWORD offs
= file
->arraydesc_seg
.len
;
9448 /* TODO: we should check for duplicates, but that's harder because each
9449 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9450 * at the library-level) */
9452 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9453 if(!file
->arraydesc_seg
.data
)
9454 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9456 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9457 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9459 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9460 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9461 for(i
= 0; i
< desc
->cDims
; ++i
){
9462 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9463 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9469 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9475 VARTYPE vt
, subtype
;
9486 vt
= desc
->vt
& VT_TYPEMASK
;
9488 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9490 encoded
[1] = WMSFT_append_typedesc(desc
->lptdesc
, file
, &mix
, out_size
);
9491 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9493 *out_size
+= 2 * sizeof(DWORD
);
9494 }else if(vt
== VT_CARRAY
){
9495 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9496 encoded
[1] = WMSFT_append_arraydesc(desc
->lpadesc
, file
);
9498 }else if(vt
== VT_USERDEFINED
){
9499 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9500 encoded
[1] = desc
->hreftype
;
9501 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9503 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9521 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9524 data
= file
->typdesc_seg
.data
;
9525 while(offs
< file
->typdesc_seg
.len
){
9526 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9528 offs
+= sizeof(encoded
);
9531 file
->typdesc_seg
.len
+= sizeof(encoded
);
9532 if(!file
->typdesc_seg
.data
)
9533 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9535 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9537 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9542 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9544 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9545 DWORD ret
= cdguids_seg
->len
, offs
;
9546 MSFT_CDGuid
*cdguid
;
9549 if(list_empty(custdata_list
))
9552 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9553 if(!cdguids_seg
->data
){
9554 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9556 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9557 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9560 offs
= ret
+ sizeof(MSFT_CDGuid
);
9561 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9562 cdguid
->GuidOffset
= cd
->guid
->offset
;
9563 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9564 cdguid
->next
= offs
;
9565 offs
+= sizeof(MSFT_CDGuid
);
9575 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9576 WMSFT_TLBFile
*file
)
9578 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9579 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9580 MSFT_VarRecord
*varrecord
;
9581 MSFT_FuncRecord
*funcrecord
;
9583 DWORD
*name
, *offsets
, offs
;
9585 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9586 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9588 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9590 /* optional fields */
9591 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9592 if(!list_empty(&desc
->custdata_list
))
9593 recorded_size
+= 7 * sizeof(INT
);
9594 else if(desc
->HelpStringContext
!= 0)
9595 recorded_size
+= 6 * sizeof(INT
);
9597 else if(desc
->Entry
)
9598 recorded_size
+= 3 * sizeof(INT
);
9599 else if(desc
->HelpString
)
9600 recorded_size
+= 2 * sizeof(INT
);
9601 else if(desc
->helpcontext
)
9602 recorded_size
+= sizeof(INT
);
9604 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9606 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9607 if(desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9608 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9613 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9616 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9617 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9619 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9621 /* optional fields */
9622 if(desc
->HelpStringContext
!= 0)
9623 recorded_size
+= 5 * sizeof(INT
);
9624 else if(!list_empty(&desc
->custdata_list
))
9625 recorded_size
+= 4 * sizeof(INT
);
9627 else if(desc
->HelpString
)
9628 recorded_size
+= 2 * sizeof(INT
);
9629 else if(desc
->HelpContext
!= 0)
9630 recorded_size
+= sizeof(INT
);
9632 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9635 if(!recorded_size
&& !extra_size
)
9638 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9640 aux_seg
->len
+= recorded_size
+ extra_size
;
9642 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9645 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9647 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9649 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9651 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9654 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9655 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9656 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9657 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9659 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9660 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9661 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9662 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9665 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9670 * ^has_param_defaults
9671 * ^oEntry_is_intresource
9673 funcrecord
->FKCCIC
=
9674 desc
->funcdesc
.funckind
|
9675 (desc
->funcdesc
.invkind
<< 3) |
9676 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9677 (desc
->funcdesc
.callconv
<< 8);
9679 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9680 funcrecord
->FKCCIC
|= 0x2000;
9682 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9683 if(desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9684 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9685 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9688 if(paramdefault_size
> 0)
9689 funcrecord
->FKCCIC
|= 0x1000;
9691 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9692 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9694 /* optional fields */
9696 if(!list_empty(&desc
->custdata_list
)){
9697 size
+= 7 * sizeof(INT
);
9698 funcrecord
->HelpContext
= desc
->helpcontext
;
9699 if(desc
->HelpString
)
9700 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9702 funcrecord
->oHelpString
= -1;
9704 funcrecord
->oEntry
= -1;
9705 else if(IS_INTRESOURCE(desc
->Entry
))
9706 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9708 funcrecord
->oEntry
= desc
->Entry
->offset
;
9709 funcrecord
->res9
= -1;
9710 funcrecord
->resA
= -1;
9711 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9712 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9713 }else if(desc
->HelpStringContext
!= 0){
9714 size
+= 6 * sizeof(INT
);
9715 funcrecord
->HelpContext
= desc
->helpcontext
;
9716 if(desc
->HelpString
)
9717 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9719 funcrecord
->oHelpString
= -1;
9721 funcrecord
->oEntry
= -1;
9722 else if(IS_INTRESOURCE(desc
->Entry
))
9723 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9725 funcrecord
->oEntry
= desc
->Entry
->offset
;
9726 funcrecord
->res9
= -1;
9727 funcrecord
->resA
= -1;
9728 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9729 }else if(desc
->Entry
){
9730 size
+= 3 * sizeof(INT
);
9731 funcrecord
->HelpContext
= desc
->helpcontext
;
9732 if(desc
->HelpString
)
9733 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9735 funcrecord
->oHelpString
= -1;
9737 funcrecord
->oEntry
= -1;
9738 else if(IS_INTRESOURCE(desc
->Entry
))
9739 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9741 funcrecord
->oEntry
= desc
->Entry
->offset
;
9742 }else if(desc
->HelpString
){
9743 size
+= 2 * sizeof(INT
);
9744 funcrecord
->HelpContext
= desc
->helpcontext
;
9745 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9746 }else if(desc
->helpcontext
){
9747 size
+= sizeof(INT
);
9748 funcrecord
->HelpContext
= desc
->helpcontext
;
9751 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9752 size
+= paramdefault_size
;
9754 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9755 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9757 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9758 if(desc
->pParamDesc
[j
].Name
)
9759 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9762 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.wParamFlags
;
9764 if(paramdefault_size
){
9765 if(desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9766 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.pparamdescex
->varDefaultValue
, file
);
9767 else if(paramdefault_size
)
9772 size
+= sizeof(MSFT_ParameterInfo
);
9775 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9781 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9784 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9785 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9786 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9787 DWORD size
= 5 * sizeof(INT
);
9789 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9790 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9791 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9792 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9794 if(desc
->vardesc
.varkind
== VAR_CONST
){
9795 varrecord
->vardescsize
+= sizeof(VARIANT
);
9796 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.lpvarValue
, file
);
9798 varrecord
->OffsValue
= desc
->vardesc
.oInst
;
9801 if(desc
->HelpStringContext
!= 0){
9802 size
+= 5 * sizeof(INT
);
9803 varrecord
->HelpContext
= desc
->HelpContext
;
9804 if(desc
->HelpString
)
9805 varrecord
->HelpString
= desc
->HelpString
->offset
;
9807 varrecord
->HelpString
= -1;
9808 varrecord
->res9
= -1;
9809 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9810 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9811 }else if(!list_empty(&desc
->custdata_list
)){
9812 size
+= 4 * sizeof(INT
);
9813 varrecord
->HelpContext
= desc
->HelpContext
;
9814 if(desc
->HelpString
)
9815 varrecord
->HelpString
= desc
->HelpString
->offset
;
9817 varrecord
->HelpString
= -1;
9818 varrecord
->res9
= -1;
9819 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9820 }else if(desc
->HelpString
){
9821 size
+= 2 * sizeof(INT
);
9822 varrecord
->HelpContext
= desc
->HelpContext
;
9823 if(desc
->HelpString
)
9824 varrecord
->HelpString
= desc
->HelpString
->offset
;
9826 varrecord
->HelpString
= -1;
9827 }else if(desc
->HelpContext
!= 0){
9828 size
+= sizeof(INT
);
9829 varrecord
->HelpContext
= desc
->HelpContext
;
9832 varrecord
->Info
= size
| (i
<< 16);
9838 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9841 memid
= (MEMBERID
*)varrecord
;
9842 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9843 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9844 *memid
= desc
->funcdesc
.memid
;
9847 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9848 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9849 *memid
= desc
->vardesc
.memid
;
9853 name
= (DWORD
*)memid
;
9854 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9855 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9857 *name
= desc
->Name
->offset
;
9862 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9863 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9865 *name
= desc
->Name
->offset
;
9874 typedef struct tagWMSFT_RefChunk
{
9881 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9883 DWORD offs
= file
->ref_seg
.len
, i
;
9884 WMSFT_RefChunk
*chunk
;
9886 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9887 if(!file
->ref_seg
.data
)
9888 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9890 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9892 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9894 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9895 chunk
->href
= info
->impltypes
[i
].hRef
;
9896 chunk
->res04
= info
->impltypes
[i
].implflags
;
9898 if(i
< info
->typeattr
.cImplTypes
- 1)
9899 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9908 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9912 size
= sizeof(MSFT_TypeInfoBase
);
9915 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9916 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9917 base
->typekind
= TKIND_DISPATCH
;
9919 base
->typekind
= info
->typeattr
.typekind
;
9920 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9921 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
9922 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9927 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
9933 base
->posguid
= info
->guid
->offset
;
9936 base
->flags
= info
->typeattr
.wTypeFlags
;
9938 base
->NameOffset
= info
->Name
->offset
;
9940 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9941 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9943 base
->NameOffset
= -1;
9945 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
9947 base
->docstringoffs
= info
->DocString
->offset
;
9949 base
->docstringoffs
= -1;
9950 base
->helpstringcontext
= info
->dwHelpStringContext
;
9951 base
->helpcontext
= info
->dwHelpContext
;
9952 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9953 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
9954 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
9955 base
->size
= info
->typeattr
.cbSizeInstance
;
9956 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
9957 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9958 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
9959 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9960 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
9962 base
->datatype1
= info
->DllName
->offset
;
9964 base
->datatype1
= -1;
9966 if(info
->typeattr
.cImplTypes
> 0)
9967 base
->datatype1
= info
->impltypes
[0].hRef
;
9969 base
->datatype1
= -1;
9971 base
->datatype2
= index
; /* FIXME: i think there's more here */
9979 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9983 file
->typeinfo_seg
.len
= 0;
9984 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9985 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9986 *junk
= file
->typeinfo_seg
.len
;
9988 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9991 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9992 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9994 file
->aux_seg
.len
= 0;
9995 file
->aux_seg
.data
= NULL
;
9997 file
->typeinfo_seg
.len
= 0;
9998 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9999 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
10000 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
10001 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
10005 typedef struct tagWMSFT_ImpFile
{
10011 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10014 WMSFT_ImpFile
*impfile
;
10016 DWORD last_offs
= 0;
10018 file
->impfile_seg
.len
= 0;
10019 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10023 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10027 path
= implib
->name
;
10028 size
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
), NULL
, 0, NULL
, NULL
);
10030 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10033 size
+= sizeof(INT16
);
10035 size
= (size
+ 4) & ~0x3;
10039 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
10042 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
10044 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10045 int strlen
= 0, size
;
10047 impfile
= (WMSFT_ImpFile
*)data
;
10048 impfile
->guid_offs
= implib
->guid
->offset
;
10049 impfile
->lcid
= implib
->lcid
;
10050 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
10052 data
+= sizeof(WMSFT_ImpFile
);
10055 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10059 path
= implib
->name
;
10060 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
),
10061 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
10063 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10066 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
10068 size
= strlen
+ sizeof(INT16
);
10070 size
= (size
+ 4) & ~0x3;
10073 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
10076 implib
->offset
= last_offs
;
10077 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
10081 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10083 MSFT_ImpInfo
*info
;
10084 TLBRefType
*ref_type
;
10087 WMSFT_compile_impfile(This
, file
);
10089 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
10090 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
10092 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
10093 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
10094 if(ref_type
->index
== TLB_REF_USE_GUID
){
10095 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
10096 info
->oGuid
= ref_type
->guid
->offset
;
10098 info
->oGuid
= ref_type
->index
;
10099 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
10105 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10107 file
->guidhash_seg
.len
= 0x80;
10108 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
10109 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
10112 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10114 file
->namehash_seg
.len
= 0x200;
10115 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
10116 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
10119 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
10121 if(contents
&& contents
->len
){
10122 segdir
->offset
= *running_offset
;
10123 segdir
->length
= contents
->len
;
10124 *running_offset
+= segdir
->length
;
10126 segdir
->offset
= -1;
10127 segdir
->length
= 0;
10130 /* TODO: do these ever change? */
10131 segdir
->res08
= -1;
10132 segdir
->res0c
= 0xf;
10135 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10139 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10142 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10146 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10148 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10149 base
->memoffset
+= file_len
;
10156 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10158 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
10159 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
10160 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
10161 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
10162 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
10163 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
10164 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
10165 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
10166 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
10167 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
10168 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
10169 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
10170 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
10171 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
10174 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10176 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10177 WMSFT_TLBFile file
;
10178 DWORD written
, junk_size
, junk_offs
, running_offset
;
10185 TRACE("%p\n", This
);
10187 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10188 if(This
->typeinfos
[i
]->needs_layout
)
10189 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10191 memset(&file
, 0, sizeof(file
));
10193 file
.header
.magic1
= 0x5446534D;
10194 file
.header
.magic2
= 0x00010002;
10195 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10196 file
.header
.lcid2
= This
->set_lcid
;
10197 file
.header
.varflags
= 0x40 | This
->syskind
;
10198 if (This
->HelpFile
)
10199 file
.header
.varflags
|= 0x10;
10200 if (This
->HelpStringDll
)
10201 file
.header
.varflags
|= HELPDLLFLAG
;
10202 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10203 file
.header
.flags
= This
->libflags
;
10204 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10205 file
.header
.helpcontext
= This
->dwHelpContext
;
10206 file
.header
.res44
= 0x20;
10207 file
.header
.res48
= 0x80;
10208 file
.header
.dispatchpos
= This
->dispatch_href
;
10210 WMSFT_compile_namehash(This
, &file
);
10211 /* do name and string compilation to get offsets for other compilations */
10212 hres
= WMSFT_compile_names(This
, &file
);
10214 WMSFT_free_file(&file
);
10218 hres
= WMSFT_compile_strings(This
, &file
);
10220 WMSFT_free_file(&file
);
10224 WMSFT_compile_guidhash(This
, &file
);
10225 hres
= WMSFT_compile_guids(This
, &file
);
10227 WMSFT_free_file(&file
);
10232 file
.header
.helpfile
= This
->HelpFile
->offset
;
10234 file
.header
.helpfile
= -1;
10236 if(This
->DocString
)
10237 file
.header
.helpstring
= This
->DocString
->offset
;
10239 file
.header
.helpstring
= -1;
10241 /* do some more segment compilation */
10242 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10243 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10246 file
.header
.NameOffset
= This
->Name
->offset
;
10248 file
.header
.NameOffset
= -1;
10250 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10253 file
.header
.posguid
= This
->guid
->offset
;
10255 file
.header
.posguid
= -1;
10257 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10258 if(file
.header
.varflags
& HELPDLLFLAG
)
10259 junk_size
+= sizeof(DWORD
);
10261 junk
= heap_alloc_zero(junk_size
);
10262 if(file
.header
.varflags
& HELPDLLFLAG
){
10263 *junk
= This
->HelpStringDll
->offset
;
10272 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10273 WMSFT_compile_impinfo(This
, &file
);
10275 running_offset
= 0;
10277 TRACE("header at: 0x%lx\n", running_offset
);
10278 running_offset
+= sizeof(file
.header
);
10280 TRACE("junk at: 0x%lx\n", running_offset
);
10281 running_offset
+= junk_size
;
10283 TRACE("segdir at: 0x%lx\n", running_offset
);
10284 running_offset
+= sizeof(file
.segdir
);
10286 TRACE("typeinfo at: 0x%lx\n", running_offset
);
10287 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10289 TRACE("guidhashtab at: 0x%lx\n", running_offset
);
10290 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10292 TRACE("guidtab at: 0x%lx\n", running_offset
);
10293 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10295 TRACE("reftab at: 0x%lx\n", running_offset
);
10296 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10298 TRACE("impinfo at: 0x%lx\n", running_offset
);
10299 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10301 TRACE("impfiles at: 0x%lx\n", running_offset
);
10302 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10304 TRACE("namehashtab at: 0x%lx\n", running_offset
);
10305 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10307 TRACE("nametab at: 0x%lx\n", running_offset
);
10308 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10310 TRACE("stringtab at: 0x%lx\n", running_offset
);
10311 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10313 TRACE("typdesc at: 0x%lx\n", running_offset
);
10314 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10316 TRACE("arraydescriptions at: 0x%lx\n", running_offset
);
10317 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10319 TRACE("custdata at: 0x%lx\n", running_offset
);
10320 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10322 TRACE("cdguids at: 0x%lx\n", running_offset
);
10323 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10325 TRACE("res0e at: 0x%lx\n", running_offset
);
10326 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10328 TRACE("res0f at: 0x%lx\n", running_offset
);
10329 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10331 TRACE("aux_seg at: 0x%lx\n", running_offset
);
10333 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10335 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10336 FILE_ATTRIBUTE_NORMAL
, 0);
10337 if (outfile
== INVALID_HANDLE_VALUE
){
10338 WMSFT_free_file(&file
);
10340 return TYPE_E_IOERROR
;
10343 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10345 WMSFT_free_file(&file
);
10346 CloseHandle(outfile
);
10348 return TYPE_E_IOERROR
;
10351 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10354 WMSFT_free_file(&file
);
10355 CloseHandle(outfile
);
10356 return TYPE_E_IOERROR
;
10359 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10361 WMSFT_free_file(&file
);
10362 CloseHandle(outfile
);
10363 return TYPE_E_IOERROR
;
10366 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10367 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10368 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10369 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10370 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10371 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10372 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10373 WMSFT_write_segment(outfile
, &file
.name_seg
);
10374 WMSFT_write_segment(outfile
, &file
.string_seg
);
10375 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10376 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10377 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10378 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10379 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10381 WMSFT_free_file(&file
);
10383 CloseHandle(outfile
);
10388 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10391 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10392 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10396 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10397 REFGUID guid
, VARIANT
*varVal
)
10399 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10402 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10404 if (!guid
|| !varVal
)
10405 return E_INVALIDARG
;
10407 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10409 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10412 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10413 ULONG helpStringContext
)
10415 FIXME("%p, %lu - stub\n", iface
, helpStringContext
);
10419 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10422 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10423 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10426 return E_INVALIDARG
;
10428 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10433 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10434 ICreateTypeLib2_fnQueryInterface
,
10435 ICreateTypeLib2_fnAddRef
,
10436 ICreateTypeLib2_fnRelease
,
10437 ICreateTypeLib2_fnCreateTypeInfo
,
10438 ICreateTypeLib2_fnSetName
,
10439 ICreateTypeLib2_fnSetVersion
,
10440 ICreateTypeLib2_fnSetGuid
,
10441 ICreateTypeLib2_fnSetDocString
,
10442 ICreateTypeLib2_fnSetHelpFileName
,
10443 ICreateTypeLib2_fnSetHelpContext
,
10444 ICreateTypeLib2_fnSetLcid
,
10445 ICreateTypeLib2_fnSetLibFlags
,
10446 ICreateTypeLib2_fnSaveAllChanges
,
10447 ICreateTypeLib2_fnDeleteTypeInfo
,
10448 ICreateTypeLib2_fnSetCustData
,
10449 ICreateTypeLib2_fnSetHelpStringContext
,
10450 ICreateTypeLib2_fnSetHelpStringDll
10453 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10454 REFIID riid
, void **object
)
10456 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10458 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10461 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10463 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10465 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10468 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10470 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10472 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10475 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10478 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10480 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10482 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10487 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10490 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10494 TRACE("%p %x\n", This
, typeFlags
);
10496 if (typeFlags
& TYPEFLAG_FDUAL
) {
10498 ITypeInfo
*dispatch
;
10502 hres
= LoadTypeLib(L
"stdole2.tlb", &stdole
);
10506 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10507 ITypeLib_Release(stdole
);
10511 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10512 ITypeInfo_Release(dispatch
);
10517 old_flags
= This
->typeattr
.wTypeFlags
;
10518 This
->typeattr
.wTypeFlags
= typeFlags
;
10520 hres
= ICreateTypeInfo2_LayOut(iface
);
10521 if (FAILED(hres
)) {
10522 This
->typeattr
.wTypeFlags
= old_flags
;
10529 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10532 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10534 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10537 return E_INVALIDARG
;
10539 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10544 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10547 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10549 TRACE("%p, %ld.\n", iface
, helpContext
);
10551 This
->dwHelpContext
= helpContext
;
10556 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10557 WORD majorVerNum
, WORD minorVerNum
)
10559 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10561 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10563 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10564 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10569 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10570 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10572 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10574 ITypeLib
*container
;
10575 TLBRefType
*ref_type
;
10577 TYPEATTR
*typeattr
;
10581 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10583 if (!typeInfo
|| !refType
)
10584 return E_INVALIDARG
;
10586 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10590 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10591 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10593 ITypeLib_Release(container
);
10595 *refType
= target
->hreftype
;
10600 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10601 if (FAILED(hres
)) {
10602 ITypeLib_Release(container
);
10606 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10607 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10608 implib
->lcid
== libattr
->lcid
&&
10609 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10610 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10614 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10615 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10617 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10618 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10619 implib
->name
= SysAllocString(our_container
->path
);
10621 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10622 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10624 implib
->name
= NULL
;
10625 TRACE("QueryPathOfRegTypeLib failed, no name stored: %#lx.\n", hres
);
10629 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10630 implib
->lcid
= libattr
->lcid
;
10631 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10632 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10634 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10637 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10638 ITypeLib_Release(container
);
10640 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10645 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10646 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10647 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10648 ref_type
->tkind
== typeattr
->typekind
)
10653 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10654 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10656 ref_type
->tkind
= typeattr
->typekind
;
10657 ref_type
->pImpTLInfo
= implib
;
10658 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10660 ref_type
->index
= TLB_REF_USE_GUID
;
10662 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10664 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10667 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10669 *refType
= ref_type
->reference
| 0x1;
10671 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10672 This
->pTypeLib
->dispatch_href
= *refType
;
10677 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10678 UINT index
, FUNCDESC
*funcDesc
)
10680 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10681 TLBFuncDesc tmp_func_desc
, *func_desc
;
10686 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10688 if (!funcDesc
|| funcDesc
->oVft
& 3)
10689 return E_INVALIDARG
;
10691 switch (This
->typeattr
.typekind
) {
10693 if (funcDesc
->funckind
!= FUNC_STATIC
)
10694 return TYPE_E_BADMODULEKIND
;
10696 case TKIND_DISPATCH
:
10697 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10698 return TYPE_E_BADMODULEKIND
;
10701 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10702 return TYPE_E_BADMODULEKIND
;
10705 if (index
> This
->typeattr
.cFuncs
)
10706 return TYPE_E_ELEMENTNOTFOUND
;
10708 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10709 !funcDesc
->cParams
)
10710 return TYPE_E_INCONSISTENTPROPFUNCS
;
10713 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10714 funcDesc
->oVft
% 8 != 0)
10715 return E_INVALIDARG
;
10718 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10719 TLBFuncDesc_Constructor(&tmp_func_desc
);
10721 tmp_func_desc
.funcdesc
= *funcDesc
;
10723 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10724 tmp_func_desc
.funcdesc
.oVft
|= 1;
10726 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10727 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10728 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10730 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10731 tmp_func_desc
.funcdesc
.cScodes
= 0;
10734 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10735 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10736 buf_size
+= sizeof(ELEMDESC
);
10737 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10739 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10740 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10742 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10743 if (FAILED(hres
)) {
10744 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10745 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10749 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10750 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10751 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10752 if (FAILED(hres
)) {
10753 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10754 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10757 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10758 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10759 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10760 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].paramdesc
.pparamdescex
->varDefaultValue
);
10761 if (FAILED(hres
)) {
10762 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10763 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10769 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10771 if (This
->funcdescs
) {
10772 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10773 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10775 if (index
< This
->typeattr
.cFuncs
) {
10776 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10777 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10778 func_desc
= This
->funcdescs
+ index
;
10780 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10782 /* move custdata lists to the new memory location */
10783 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10785 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
10788 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10790 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10791 list_init(&func_desc
->custdata_list
);
10793 ++This
->typeattr
.cFuncs
;
10795 This
->needs_layout
= TRUE
;
10800 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10801 UINT index
, HREFTYPE refType
)
10803 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10804 TLBImplType
*impl_type
;
10807 TRACE("%p, %u, %ld.\n", iface
, index
, refType
);
10809 switch(This
->typeattr
.typekind
){
10810 case TKIND_COCLASS
: {
10812 FIXME("Unhandled index: -1\n");
10816 if(index
!= This
->typeattr
.cImplTypes
)
10817 return TYPE_E_ELEMENTNOTFOUND
;
10821 case TKIND_INTERFACE
:
10822 case TKIND_DISPATCH
:
10823 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10824 return TYPE_E_ELEMENTNOTFOUND
;
10827 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10831 if (This
->impltypes
){
10834 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10835 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10837 if (index
< This
->typeattr
.cImplTypes
) {
10838 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10839 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10840 impl_type
= This
->impltypes
+ index
;
10842 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10844 /* move custdata lists to the new memory location */
10845 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10847 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
10850 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10852 memset(impl_type
, 0, sizeof(TLBImplType
));
10853 TLBImplType_Constructor(impl_type
);
10854 impl_type
->hRef
= refType
;
10856 ++This
->typeattr
.cImplTypes
;
10858 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10859 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10861 hres
= ICreateTypeInfo2_LayOut(iface
);
10868 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10869 UINT index
, INT implTypeFlags
)
10871 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10872 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10874 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10876 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10877 return TYPE_E_BADMODULEKIND
;
10879 if (index
>= This
->typeattr
.cImplTypes
)
10880 return TYPE_E_ELEMENTNOTFOUND
;
10882 impl_type
->implflags
= implTypeFlags
;
10887 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10890 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10892 TRACE("%p %d\n", This
, alignment
);
10894 This
->typeattr
.cbAlignment
= alignment
;
10899 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10902 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10904 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10907 return E_INVALIDARG
;
10909 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10911 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10916 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10917 UINT index
, VARDESC
*varDesc
)
10919 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10920 TLBVarDesc
*var_desc
;
10923 TRACE("%p %u %p\n", This
, index
, varDesc
);
10925 if (This
->vardescs
){
10928 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10929 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
10931 if (index
< This
->typeattr
.cVars
) {
10932 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10933 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
10934 var_desc
= This
->vardescs
+ index
;
10936 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
10938 /* move custdata lists to the new memory location */
10939 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
10941 TLB_relink_custdata(&This
->vardescs
[i
].custdata_list
);
10944 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10946 TLBVarDesc_Constructor(var_desc
);
10947 hr
= TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10950 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10952 ++This
->typeattr
.cVars
;
10954 This
->needs_layout
= TRUE
;
10959 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10960 UINT index
, LPOLESTR
*names
, UINT numNames
)
10962 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10963 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10966 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10969 return E_INVALIDARG
;
10971 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
10972 return TYPE_E_ELEMENTNOTFOUND
;
10974 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10975 if(numNames
> func_desc
->funcdesc
.cParams
)
10976 return TYPE_E_ELEMENTNOTFOUND
;
10978 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10979 return TYPE_E_ELEMENTNOTFOUND
;
10981 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
10982 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10983 if (iter
->Name
&& !wcscmp(TLB_get_bstr(iter
->Name
), *names
)) {
10984 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10985 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10986 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10988 return TYPE_E_AMBIGUOUSNAME
;
10992 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10994 for (i
= 1; i
< numNames
; ++i
) {
10995 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10996 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
11002 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
11003 UINT index
, LPOLESTR name
)
11005 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11007 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
11010 return E_INVALIDARG
;
11012 if(index
>= This
->typeattr
.cVars
)
11013 return TYPE_E_ELEMENTNOTFOUND
;
11015 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11019 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
11020 TYPEDESC
*tdescAlias
)
11022 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11025 TRACE("%p %p\n", This
, tdescAlias
);
11028 return E_INVALIDARG
;
11030 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
11031 return TYPE_E_BADMODULEKIND
;
11033 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
11037 heap_free(This
->tdescAlias
);
11038 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
11039 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
11044 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
11045 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
11047 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11048 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
11052 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
11053 UINT index
, LPOLESTR docString
)
11055 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11056 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11058 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11061 return E_INVALIDARG
;
11063 if(index
>= This
->typeattr
.cFuncs
)
11064 return TYPE_E_ELEMENTNOTFOUND
;
11066 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11071 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
11072 UINT index
, LPOLESTR docString
)
11074 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11075 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11077 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11080 return E_INVALIDARG
;
11082 if(index
>= This
->typeattr
.cVars
)
11083 return TYPE_E_ELEMENTNOTFOUND
;
11085 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11090 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
11091 UINT index
, DWORD helpContext
)
11093 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11094 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11096 TRACE("%p, %u, %ld.\n", iface
, index
, helpContext
);
11098 if(index
>= This
->typeattr
.cFuncs
)
11099 return TYPE_E_ELEMENTNOTFOUND
;
11101 func_desc
->helpcontext
= helpContext
;
11106 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
11107 UINT index
, DWORD helpContext
)
11109 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11110 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11112 TRACE("%p, %u, %ld.\n", iface
, index
, helpContext
);
11114 if(index
>= This
->typeattr
.cVars
)
11115 return TYPE_E_ELEMENTNOTFOUND
;
11117 var_desc
->HelpContext
= helpContext
;
11122 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
11123 UINT index
, BSTR bstrMops
)
11125 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11126 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
11130 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
11133 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11135 TRACE("%p %p\n", This
, idlDesc
);
11138 return E_INVALIDARG
;
11140 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11141 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11146 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11148 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11149 ITypeInfo2
*tinfo
= &This
->ITypeInfo2_iface
;
11150 TLBFuncDesc
*func_desc
;
11151 UINT user_vft
= 0, i
, depth
= 0;
11152 HRESULT hres
= S_OK
;
11154 TRACE("%p\n", This
);
11156 This
->needs_layout
= FALSE
;
11158 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11163 hres
= ITypeInfo2_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11165 if (SUCCEEDED(hres
)) {
11166 hres
= ITypeInfo2_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11168 if (SUCCEEDED(hres
)) {
11169 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11170 if (FAILED(hres
)) {
11171 ITypeInfo_Release(inh
);
11174 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11175 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11179 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11180 if(SUCCEEDED(hres
)){
11182 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11183 if(SUCCEEDED(hres
)){
11184 ITypeInfo_Release(inh
);
11188 }while(SUCCEEDED(hres
));
11191 ITypeInfo_Release(inh
);
11192 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11193 This
->typeattr
.cbSizeVft
= 0;
11197 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11198 This
->typeattr
.cbSizeVft
= 0;
11202 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11203 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11205 This
->typeattr
.cbSizeVft
= 0;
11207 func_desc
= This
->funcdescs
;
11209 while (i
< This
->typeattr
.cFuncs
) {
11210 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11211 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11213 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11214 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11216 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11218 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11221 BOOL reset
= FALSE
;
11223 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11225 iter
= This
->funcdescs
;
11226 while (j
< This
->typeattr
.cFuncs
) {
11227 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11229 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11232 ++func_desc
->funcdesc
.memid
;
11233 iter
= This
->funcdescs
;
11246 if (user_vft
> This
->typeattr
.cbSizeVft
)
11247 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11249 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11250 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11251 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11253 BOOL reset
= FALSE
;
11256 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11258 iter
= This
->vardescs
;
11259 while (j
< This
->typeattr
.cVars
) {
11260 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11262 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11265 ++var_desc
->vardesc
.memid
;
11266 iter
= This
->vardescs
;
11279 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11282 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11285 TRACE("%p %u\n", This
, index
);
11287 if (index
>= This
->typeattr
.cFuncs
)
11288 return TYPE_E_ELEMENTNOTFOUND
;
11290 typeinfo_release_funcdesc(&This
->funcdescs
[index
]);
11292 --This
->typeattr
.cFuncs
;
11293 if (index
!= This
->typeattr
.cFuncs
)
11295 memmove(This
->funcdescs
+ index
, This
->funcdescs
+ index
+ 1,
11296 sizeof(*This
->funcdescs
) * (This
->typeattr
.cFuncs
- index
));
11297 for (i
= index
; i
< This
->typeattr
.cFuncs
; ++i
)
11298 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
11301 This
->needs_layout
= TRUE
;
11306 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11307 MEMBERID memid
, INVOKEKIND invKind
)
11309 FIXME("%p, %#lx, %d - stub\n", iface
, memid
, invKind
);
11313 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11316 FIXME("%p, %u - stub\n", iface
, index
);
11320 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11323 FIXME("%p, %#lx - stub\n", iface
, memid
);
11327 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11330 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11333 TRACE("%p %u\n", This
, index
);
11335 if (index
>= This
->typeattr
.cImplTypes
)
11336 return TYPE_E_ELEMENTNOTFOUND
;
11338 TLB_FreeCustData(&This
->impltypes
[index
].custdata_list
);
11339 --This
->typeattr
.cImplTypes
;
11341 if (index
< This
->typeattr
.cImplTypes
)
11343 memmove(This
->impltypes
+ index
, This
->impltypes
+ index
+ 1, (This
->typeattr
.cImplTypes
- index
) *
11344 sizeof(*This
->impltypes
));
11345 for (i
= index
; i
< This
->typeattr
.cImplTypes
; ++i
)
11346 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
11352 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11353 REFGUID guid
, VARIANT
*varVal
)
11357 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11359 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11361 if (!guid
|| !varVal
)
11362 return E_INVALIDARG
;
11364 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11366 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11369 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11370 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11372 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11373 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11377 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11378 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11380 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11381 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11385 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11386 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11388 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11389 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11393 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11394 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11396 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11397 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11401 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11402 ULONG helpStringContext
)
11404 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11406 TRACE("%p, %lu.\n", iface
, helpStringContext
);
11408 This
->dwHelpStringContext
= helpStringContext
;
11413 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11414 UINT index
, ULONG helpStringContext
)
11416 FIXME("%p, %u, %lu - stub\n", iface
, index
, helpStringContext
);
11420 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11421 UINT index
, ULONG helpStringContext
)
11423 FIXME("%p, %u, %lu - stub\n", iface
, index
, helpStringContext
);
11427 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11429 FIXME("%p - stub\n", iface
);
11433 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11436 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11438 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11441 return E_INVALIDARG
;
11443 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11448 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11449 ICreateTypeInfo2_fnQueryInterface
,
11450 ICreateTypeInfo2_fnAddRef
,
11451 ICreateTypeInfo2_fnRelease
,
11452 ICreateTypeInfo2_fnSetGuid
,
11453 ICreateTypeInfo2_fnSetTypeFlags
,
11454 ICreateTypeInfo2_fnSetDocString
,
11455 ICreateTypeInfo2_fnSetHelpContext
,
11456 ICreateTypeInfo2_fnSetVersion
,
11457 ICreateTypeInfo2_fnAddRefTypeInfo
,
11458 ICreateTypeInfo2_fnAddFuncDesc
,
11459 ICreateTypeInfo2_fnAddImplType
,
11460 ICreateTypeInfo2_fnSetImplTypeFlags
,
11461 ICreateTypeInfo2_fnSetAlignment
,
11462 ICreateTypeInfo2_fnSetSchema
,
11463 ICreateTypeInfo2_fnAddVarDesc
,
11464 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11465 ICreateTypeInfo2_fnSetVarName
,
11466 ICreateTypeInfo2_fnSetTypeDescAlias
,
11467 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11468 ICreateTypeInfo2_fnSetFuncDocString
,
11469 ICreateTypeInfo2_fnSetVarDocString
,
11470 ICreateTypeInfo2_fnSetFuncHelpContext
,
11471 ICreateTypeInfo2_fnSetVarHelpContext
,
11472 ICreateTypeInfo2_fnSetMops
,
11473 ICreateTypeInfo2_fnSetTypeIdldesc
,
11474 ICreateTypeInfo2_fnLayOut
,
11475 ICreateTypeInfo2_fnDeleteFuncDesc
,
11476 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11477 ICreateTypeInfo2_fnDeleteVarDesc
,
11478 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11479 ICreateTypeInfo2_fnDeleteImplType
,
11480 ICreateTypeInfo2_fnSetCustData
,
11481 ICreateTypeInfo2_fnSetFuncCustData
,
11482 ICreateTypeInfo2_fnSetParamCustData
,
11483 ICreateTypeInfo2_fnSetVarCustData
,
11484 ICreateTypeInfo2_fnSetImplTypeCustData
,
11485 ICreateTypeInfo2_fnSetHelpStringContext
,
11486 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11487 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11488 ICreateTypeInfo2_fnInvalidate
,
11489 ICreateTypeInfo2_fnSetName
11492 /******************************************************************************
11493 * ClearCustData (OLEAUT32.171)
11495 * Clear a custom data type's data.
11498 * lpCust [I] The custom data type instance
11503 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11505 if (lpCust
&& lpCust
->cCustData
)
11507 if (lpCust
->prgCustData
)
11511 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11512 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11514 CoTaskMemFree(lpCust
->prgCustData
);
11515 lpCust
->prgCustData
= NULL
;
11517 lpCust
->cCustData
= 0;