4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
46 * -. lousy fatal error handling
57 #define NONAMELESSUNION
70 #include "wine/debug.h"
73 #include "wine/heap.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
91 WORD type_id
; /* Type identifier */
92 WORD count
; /* Number of resources of this type */
93 DWORD resloader
; /* SetResourceHandler() */
99 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
100 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
101 static void TLB_FreeVarDesc(VARDESC
*);
103 /****************************************************************************
106 * Takes p_iVal (which is in little endian) and returns it
107 * in the host machine's byte order.
109 #ifdef WORDS_BIGENDIAN
110 static WORD
FromLEWord(WORD p_iVal
)
112 return (((p_iVal
& 0x00FF) << 8) |
113 ((p_iVal
& 0xFF00) >> 8));
117 static DWORD
FromLEDWord(DWORD p_iVal
)
119 return (((p_iVal
& 0x000000FF) << 24) |
120 ((p_iVal
& 0x0000FF00) << 8) |
121 ((p_iVal
& 0x00FF0000) >> 8) |
122 ((p_iVal
& 0xFF000000) >> 24));
125 #define FromLEWord(X) (X)
126 #define FromLEDWord(X) (X)
129 #define DISPATCH_HREF_OFFSET 0x01000000
130 #define DISPATCH_HREF_MASK 0xff000000
132 /****************************************************************************
135 * Fix byte order in any structure if necessary
137 #ifdef WORDS_BIGENDIAN
138 static void FromLEWords(void *p_Val
, int p_iSize
)
142 p_iSize
/= sizeof(WORD
);
145 *Val
= FromLEWord(*Val
);
152 static void FromLEDWords(void *p_Val
, int p_iSize
)
156 p_iSize
/= sizeof(DWORD
);
159 *Val
= FromLEDWord(*Val
);
165 #define FromLEWords(X,Y) /*nothing*/
166 #define FromLEDWords(X,Y) /*nothing*/
170 * Find a typelib key which matches a requested maj.min version.
172 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
177 INT best_maj
= -1, best_min
= -1;
180 lstrcpyW( buffer
, L
"Typelib\\" );
181 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
186 len
= sizeof(key_name
);
188 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
192 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
196 if (*wMaj
== 0xffff && *wMin
== 0xffff)
198 if (v_maj
> best_maj
) best_maj
= v_maj
;
199 if (v_min
> best_min
) best_min
= v_min
;
201 else if (*wMaj
== v_maj
)
208 break; /* exact match */
210 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
213 len
= sizeof(key_name
);
217 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
219 if (*wMaj
== 0xffff && *wMin
== 0xffff)
221 if (best_maj
>= 0 && best_min
>= 0)
229 if (*wMaj
== best_maj
&& best_min
>= 0)
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
241 lstrcpyW( buffer
, L
"Typelib\\" );
242 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
243 swprintf( buffer
+ lstrlenW(buffer
), 20, L
"\\%x.%x", wMaj
, wMin
);
247 /* get the path of an interface key, in the form "Interface\\<guid>" */
248 /* buffer must be at least 50 characters long */
249 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
251 lstrcpyW( buffer
, L
"Interface\\" );
252 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
256 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
257 /* buffer must be at least 16 characters long */
258 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
260 swprintf( buffer
, 16, L
"%lx\\", lcid
);
263 case SYS_WIN16
: lstrcatW( buffer
, L
"win16" ); break;
264 case SYS_WIN32
: lstrcatW( buffer
, L
"win32" ); break;
265 case SYS_WIN64
: lstrcatW( buffer
, L
"win64" ); break;
267 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
273 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
275 struct tlibredirect_data
289 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
290 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
291 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
293 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
297 WCHAR Path
[MAX_PATH
];
300 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
304 ACTCTX_SECTION_KEYED_DATA data
;
306 data
.cbSize
= sizeof(data
);
307 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
309 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
313 if ((wMaj
!= 0xffff || wMin
!= 0xffff) && (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
))
314 return TYPE_E_LIBNOTREGISTERED
;
316 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
317 len
= SearchPathW( NULL
, nameW
, NULL
, ARRAY_SIZE( Path
), Path
, NULL
);
318 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
320 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
321 *path
= SysAllocString( Path
);
326 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
327 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
329 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
330 if (res
== ERROR_FILE_NOT_FOUND
)
332 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
333 return TYPE_E_LIBNOTREGISTERED
;
335 else if (res
!= ERROR_SUCCESS
)
337 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
338 return TYPE_E_REGISTRYACCESS
;
343 LONG dwPathLen
= sizeof(Path
);
345 get_lcid_subkey( myLCID
, syskind
, buffer
);
347 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
351 else if (myLCID
== lcid
)
353 /* try with sub-langid */
354 myLCID
= SUBLANGID(lcid
);
356 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
358 /* try with system langid */
368 *path
= SysAllocString( Path
);
373 TRACE_(typelib
)("-- 0x%08x\n", hr
);
377 /****************************************************************************
378 * QueryPathOfRegTypeLib [OLEAUT32.164]
380 * Gets the path to a registered type library.
383 * guid [I] referenced guid
384 * wMaj [I] major version
385 * wMin [I] minor version
387 * path [O] path of typelib
391 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
392 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
395 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
399 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
404 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
407 /******************************************************************************
408 * CreateTypeLib [OLEAUT32.160] creates a typelib
414 HRESULT WINAPI
CreateTypeLib(
415 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
417 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
421 /******************************************************************************
422 * LoadTypeLib [OLEAUT32.161]
424 * Loads a type library
427 * szFile [I] Name of file to load from.
428 * pptLib [O] Pointer that receives ITypeLib object on success.
435 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
437 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
439 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
440 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
443 /******************************************************************************
444 * LoadTypeLibEx [OLEAUT32.183]
446 * Loads and optionally registers a type library
452 HRESULT WINAPI
LoadTypeLibEx(
453 LPCOLESTR szFile
, /* [in] Name of file to load from */
454 REGKIND regkind
, /* [in] Specify kind of registration */
455 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
457 WCHAR szPath
[MAX_PATH
+1];
460 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
462 if (!szFile
|| !pptLib
)
467 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
472 case REGKIND_DEFAULT
:
473 /* don't register typelibs supplied with full path. Experimentation confirms the following */
474 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
475 (szFile
[0] && (szFile
[1] == ':'))) break;
476 /* else fall-through */
478 case REGKIND_REGISTER
:
479 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
481 ITypeLib_Release(*pptLib
);
489 TRACE(" returns %08x\n",res
);
493 /******************************************************************************
494 * LoadRegTypeLib [OLEAUT32.162]
496 * Loads a registered type library.
499 * rguid [I] GUID of the registered type library.
500 * wVerMajor [I] major version.
501 * wVerMinor [I] minor version.
502 * lcid [I] locale ID.
503 * ppTLib [O] pointer that receives an ITypeLib object on success.
507 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
510 HRESULT WINAPI
LoadRegTypeLib(
522 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
526 res
= LoadTypeLib(bstr
, ppTLib
);
529 if ((wVerMajor
!=0xffff || wVerMinor
!=0xffff) && *ppTLib
)
533 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
536 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
537 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
541 ITypeLib_Release(*ppTLib
);
543 res
= TYPE_E_LIBNOTREGISTERED
;
549 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
554 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
559 get_interface_key( &tattr
->guid
, keyName
);
560 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
561 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
563 const WCHAR
*proxy_clsid
;
565 if (tattr
->typekind
== TKIND_INTERFACE
|| (tattr
->wTypeFlags
& TYPEFLAG_FDUAL
))
566 proxy_clsid
= L
"{00020424-0000-0000-C000-000000000046}";
568 proxy_clsid
= L
"{00020420-0000-0000-C000-000000000046}";
571 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
572 (BYTE
*)name
, (lstrlenW(name
)+1) * sizeof(OLECHAR
));
574 if (!RegCreateKeyExW(key
, L
"ProxyStubClsid", 0, NULL
, 0, KEY_WRITE
| flag
, NULL
, &subKey
, NULL
))
576 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
, (const BYTE
*)proxy_clsid
, (lstrlenW(proxy_clsid
) + 1) * sizeof(WCHAR
));
580 if (!RegCreateKeyExW(key
, L
"ProxyStubClsid32", 0, NULL
, 0, KEY_WRITE
| flag
, NULL
, &subKey
, NULL
))
582 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
, (const BYTE
*)proxy_clsid
, (lstrlenW(proxy_clsid
) + 1) * sizeof(WCHAR
));
586 if (RegCreateKeyExW(key
, L
"TypeLib", 0, NULL
, 0,
587 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
591 StringFromGUID2(&libattr
->guid
, buffer
, 40);
592 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
593 (BYTE
*)buffer
, (lstrlenW(buffer
)+1) * sizeof(WCHAR
));
594 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%x.%x", libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
595 RegSetValueExW(subKey
, L
"Version", 0, REG_SZ
, (BYTE
*)buffer
, (lstrlenW(buffer
)+1) * sizeof(WCHAR
));
603 /******************************************************************************
604 * RegisterTypeLib [OLEAUT32.163]
605 * Adds information about a type library to the System Registry
607 * Docs: ITypeLib FAR * ptlib
608 * Docs: OLECHAR FAR* szFullPath
609 * Docs: OLECHAR FAR* szHelpDir
615 HRESULT WINAPI
RegisterTypeLib(ITypeLib
*ptlib
, const WCHAR
*szFullPath
, const WCHAR
*szHelpDir
)
626 if (ptlib
== NULL
|| szFullPath
== NULL
)
629 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
633 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
636 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
639 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
640 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
644 /* Set the human-readable name of the typelib */
645 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
649 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
650 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
656 /* Make up the name of the typelib path subkey */
657 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
659 /* Create the typelib path subkey */
660 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
661 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
663 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
664 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
672 /* Create the flags subkey */
673 if (res
== S_OK
&& RegCreateKeyExW(key
, L
"FLAGS", 0, NULL
, 0,
674 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
678 /* FIXME: is %u correct? */
679 swprintf(buf
, ARRAY_SIZE(buf
), L
"%u", attr
->wLibFlags
);
680 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
681 (BYTE
*)buf
, (lstrlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
689 /* create the helpdir subkey */
690 if (res
== S_OK
&& RegCreateKeyExW(key
, L
"HELPDIR", 0, NULL
, 0,
691 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
693 BSTR freeHelpDir
= NULL
;
696 /* if we created a new key, and helpDir was null, set the helpdir
697 to the directory which contains the typelib. However,
698 if we just opened an existing key, we leave the helpdir alone */
699 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
700 szHelpDir
= freeHelpDir
= SysAllocString(szFullPath
);
701 file_name
= wcsrchr(szHelpDir
, '\\');
702 if (file_name
&& file_name
[1]) {
703 /* possible remove a numeric \index (resource-id) */
704 WCHAR
*end_ptr
= file_name
+ 1;
705 while ('0' <= *end_ptr
&& *end_ptr
<= '9') end_ptr
++;
709 file_name
= wcsrchr(szHelpDir
, '\\');
716 /* if we have an szHelpDir, set it! */
717 if (szHelpDir
!= NULL
) {
718 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
719 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
724 SysFreeString(freeHelpDir
);
735 /* register OLE Automation-compatible interfaces for this typelib */
736 types
= ITypeLib_GetTypeInfoCount(ptlib
);
737 for (tidx
=0; tidx
<types
; tidx
++) {
738 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
739 LPOLESTR name
= NULL
;
740 ITypeInfo
*tinfo
= NULL
;
742 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
745 case TKIND_INTERFACE
:
746 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
747 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
751 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
752 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
756 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
761 TYPEATTR
*tattr
= NULL
;
762 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
765 TRACE_(typelib
)("guid=%s, flags=%04x (",
766 debugstr_guid(&tattr
->guid
),
769 if (TRACE_ON(typelib
)) {
770 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
790 /* Register all dispinterfaces (which includes dual interfaces) and
791 oleautomation interfaces */
792 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
793 kind
== TKIND_DISPATCH
)
796 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
798 /* register interface<->typelib coupling */
799 TLB_register_interface(attr
, name
, tattr
, 0);
801 /* register TLBs into the opposite registry view, too */
802 if(opposite
== KEY_WOW64_32KEY
||
803 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
804 TLB_register_interface(attr
, name
, tattr
, opposite
);
807 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
810 ITypeInfo_Release(tinfo
);
817 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
822 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
824 WCHAR subKeyName
[50];
827 /* the path to the type */
828 get_interface_key( guid
, subKeyName
);
830 /* Delete its bits */
831 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
834 RegDeleteKeyW(subKey
, L
"ProxyStubClsid");
835 RegDeleteKeyW(subKey
, L
"ProxyStubClsid32");
836 RegDeleteKeyW(subKey
, L
"TypeLib");
838 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
841 /******************************************************************************
842 * UnRegisterTypeLib [OLEAUT32.186]
843 * Removes information about a type library from the System Registry
850 HRESULT WINAPI
UnRegisterTypeLib(
851 REFGUID libid
, /* [in] Guid of the library */
852 WORD wVerMajor
, /* [in] major version */
853 WORD wVerMinor
, /* [in] minor version */
854 LCID lcid
, /* [in] locale id */
857 BSTR tlibPath
= NULL
;
860 WCHAR subKeyName
[50];
863 BOOL deleteOtherStuff
;
865 TYPEATTR
* typeAttr
= NULL
;
867 ITypeInfo
* typeInfo
= NULL
;
868 ITypeLib
* typeLib
= NULL
;
871 TRACE("(IID: %s)\n",debugstr_guid(libid
));
873 /* Create the path to the key */
874 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
876 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
878 TRACE("Unsupported syskind %i\n", syskind
);
879 result
= E_INVALIDARG
;
883 /* get the path to the typelib on disk */
884 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
885 result
= E_INVALIDARG
;
889 /* Try and open the key to the type library. */
890 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
891 result
= E_INVALIDARG
;
895 /* Try and load the type library */
896 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
897 result
= TYPE_E_INVALIDSTATE
;
901 /* remove any types registered with this typelib */
902 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
903 for (i
=0; i
<numTypes
; i
++) {
904 /* get the kind of type */
905 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
909 /* skip non-interfaces, and get type info for the type */
910 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
913 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
916 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
920 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
921 kind
== TKIND_DISPATCH
)
924 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
926 TLB_unregister_interface(&typeAttr
->guid
, 0);
928 /* unregister TLBs into the opposite registry view, too */
929 if(opposite
== KEY_WOW64_32KEY
||
930 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
931 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
936 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
938 if (typeInfo
) ITypeInfo_Release(typeInfo
);
942 /* Now, delete the type library path subkey */
943 get_lcid_subkey( lcid
, syskind
, subKeyName
);
944 RegDeleteKeyW(key
, subKeyName
);
945 *wcsrchr( subKeyName
, '\\' ) = 0; /* remove last path component */
946 RegDeleteKeyW(key
, subKeyName
);
948 /* check if there is anything besides the FLAGS/HELPDIR keys.
949 If there is, we don't delete them */
950 tmpLength
= ARRAY_SIZE(subKeyName
);
951 deleteOtherStuff
= TRUE
;
953 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
954 tmpLength
= ARRAY_SIZE(subKeyName
);
956 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
957 if (!wcscmp(subKeyName
, L
"FLAGS")) continue;
958 if (!wcscmp(subKeyName
, L
"HELPDIR")) continue;
959 deleteOtherStuff
= FALSE
;
963 /* only delete the other parts of the key if we're absolutely sure */
964 if (deleteOtherStuff
) {
965 RegDeleteKeyW(key
, L
"FLAGS");
966 RegDeleteKeyW(key
, L
"HELPDIR");
970 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
971 *wcsrchr( keyName
, '\\' ) = 0; /* remove last path component */
972 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
976 SysFreeString(tlibPath
);
977 if (typeLib
) ITypeLib_Release(typeLib
);
978 if (key
) RegCloseKey(key
);
982 /******************************************************************************
983 * RegisterTypeLibForUser [OLEAUT32.442]
984 * Adds information about a type library to the user registry
986 * Docs: ITypeLib FAR * ptlib
987 * Docs: OLECHAR FAR* szFullPath
988 * Docs: OLECHAR FAR* szHelpDir
994 HRESULT WINAPI
RegisterTypeLibForUser(
995 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
996 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
997 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1000 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1001 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1002 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1005 /******************************************************************************
1006 * UnRegisterTypeLibForUser [OLEAUT32.443]
1007 * Removes information about a type library from the user registry
1013 HRESULT WINAPI
UnRegisterTypeLibForUser(
1014 REFGUID libid
, /* [in] GUID of the library */
1015 WORD wVerMajor
, /* [in] major version */
1016 WORD wVerMinor
, /* [in] minor version */
1017 LCID lcid
, /* [in] locale id */
1020 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1021 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1022 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1025 /*======================= ITypeLib implementation =======================*/
1027 typedef struct tagTLBGuid
{
1034 typedef struct tagTLBCustData
1041 /* data structure for import typelibs */
1042 typedef struct tagTLBImpLib
1044 int offset
; /* offset in the file (MSFT)
1045 offset in nametable (SLTG)
1046 just used to identify library while reading
1048 TLBGuid
*guid
; /* libid */
1049 BSTR name
; /* name */
1051 LCID lcid
; /* lcid of imported typelib */
1053 WORD wVersionMajor
; /* major version number */
1054 WORD wVersionMinor
; /* minor version number */
1056 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1057 NULL if not yet loaded */
1061 typedef struct tagTLBString
{
1067 /* internal ITypeLib data */
1068 typedef struct tagITypeLibImpl
1070 ITypeLib2 ITypeLib2_iface
;
1071 ITypeComp ITypeComp_iface
;
1072 ICreateTypeLib2 ICreateTypeLib2_iface
;
1083 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1084 * exported to the application as a UNICODE string.
1086 struct list string_list
;
1087 struct list name_list
;
1088 struct list guid_list
;
1090 const TLBString
*Name
;
1091 const TLBString
*DocString
;
1092 const TLBString
*HelpFile
;
1093 const TLBString
*HelpStringDll
;
1094 DWORD dwHelpContext
;
1095 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1096 struct tagITypeInfoImpl
**typeinfos
;
1097 struct list custdata_list
;
1098 struct list implib_list
;
1099 int ctTypeDesc
; /* number of items in type desc array */
1100 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1101 library. Only used while reading MSFT
1103 struct list ref_list
; /* list of ref types in this typelib */
1104 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1107 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1113 static const ITypeLib2Vtbl tlbvt
;
1114 static const ITypeCompVtbl tlbtcvt
;
1115 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1117 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1119 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1122 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1124 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1127 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1129 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1132 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1134 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1137 /* ITypeLib methods */
1138 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1139 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1141 /*======================= ITypeInfo implementation =======================*/
1143 /* data for referenced types */
1144 typedef struct tagTLBRefType
1146 INT index
; /* Type index for internal ref or for external ref
1147 it the format is SLTG. -2 indicates to
1151 TLBGuid
*guid
; /* guid of the referenced type */
1152 /* if index == TLB_REF_USE_GUID */
1154 HREFTYPE reference
; /* The href of this ref */
1155 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1156 TLB_REF_INTERNAL for internal refs
1157 TLB_REF_NOT_FOUND for broken refs */
1162 #define TLB_REF_USE_GUID -2
1164 #define TLB_REF_INTERNAL (void*)-2
1165 #define TLB_REF_NOT_FOUND (void*)-1
1167 /* internal Parameter data */
1168 typedef struct tagTLBParDesc
1170 const TLBString
*Name
;
1171 struct list custdata_list
;
1174 /* internal Function data */
1175 typedef struct tagTLBFuncDesc
1177 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1178 const TLBString
*Name
; /* the name of this function */
1179 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1181 int HelpStringContext
;
1182 const TLBString
*HelpString
;
1183 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1184 struct list custdata_list
;
1187 /* internal Variable data */
1188 typedef struct tagTLBVarDesc
1190 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1191 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1192 const TLBString
*Name
; /* the name of this variable */
1194 int HelpStringContext
;
1195 const TLBString
*HelpString
;
1196 struct list custdata_list
;
1199 /* internal implemented interface data */
1200 typedef struct tagTLBImplType
1202 HREFTYPE hRef
; /* hRef of interface */
1203 int implflags
; /* IMPLFLAG_*s */
1204 struct list custdata_list
;
1207 /* internal TypeInfo data */
1208 typedef struct tagITypeInfoImpl
1210 ITypeInfo2 ITypeInfo2_iface
;
1211 ITypeComp ITypeComp_iface
;
1212 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1214 BOOL not_attached_to_typelib
;
1219 TYPEDESC
*tdescAlias
;
1221 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1222 int index
; /* index in this typelib; */
1223 HREFTYPE hreftype
; /* hreftype for app object binding */
1224 /* type libs seem to store the doc strings in ascii
1225 * so why should we do it in unicode?
1227 const TLBString
*Name
;
1228 const TLBString
*DocString
;
1229 const TLBString
*DllName
;
1230 const TLBString
*Schema
;
1231 DWORD dwHelpContext
;
1232 DWORD dwHelpStringContext
;
1235 TLBFuncDesc
*funcdescs
;
1238 TLBVarDesc
*vardescs
;
1240 /* Implemented Interfaces */
1241 TLBImplType
*impltypes
;
1243 struct list
*pcustdata_list
;
1244 struct list custdata_list
;
1247 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1249 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1252 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1254 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1257 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1259 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1262 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1264 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1267 static const ITypeInfo2Vtbl tinfvt
;
1268 static const ITypeCompVtbl tcompvt
;
1269 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1271 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1272 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1274 typedef struct tagTLBContext
1276 unsigned int oStart
; /* start of TLB in file */
1277 unsigned int pos
; /* current pos */
1278 unsigned int length
; /* total length */
1279 void *mapping
; /* memory mapping */
1280 MSFT_SegDir
* pTblDir
;
1281 ITypeLibImpl
* pLibInfo
;
1285 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1287 return str
!= NULL
? str
->str
: NULL
;
1290 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1294 return memcmp(left
, str
->str
, len
);
1297 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1299 return guid
!= NULL
? &guid
->guid
: NULL
;
1302 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1304 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1307 static int get_ptr_size(SYSKIND syskind
)
1317 WARN("Unhandled syskind: 0x%x\n", syskind
);
1324 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1325 if (pTD
->vt
& VT_RESERVED
)
1326 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1327 if (pTD
->vt
& VT_BYREF
)
1328 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1329 if (pTD
->vt
& VT_ARRAY
)
1330 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1331 if (pTD
->vt
& VT_VECTOR
)
1332 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1333 switch(pTD
->vt
& VT_TYPEMASK
) {
1334 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1335 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1336 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1337 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1338 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1339 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1340 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1341 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1342 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1343 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1344 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1345 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1346 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1347 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1348 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1349 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1350 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1351 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1352 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1353 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1354 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1355 pTD
->u
.hreftype
); break;
1356 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1357 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1358 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1359 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1361 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1362 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1364 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1365 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1366 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1369 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1373 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1375 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1376 dump_TypeDesc(&edesc
->tdesc
,buf
);
1377 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1378 MESSAGE("\t\tu.paramdesc.wParamFlags");
1379 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1380 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1381 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1382 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1383 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1384 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1385 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1386 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1387 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1389 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1391 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1392 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1393 MESSAGE("Param %d:\n",i
);
1394 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1396 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1397 switch (funcdesc
->funckind
) {
1398 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1399 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1400 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1401 case FUNC_STATIC
: MESSAGE("static");break;
1402 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1403 default: MESSAGE("unknown");break;
1405 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1406 switch (funcdesc
->invkind
) {
1407 case INVOKE_FUNC
: MESSAGE("func");break;
1408 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1409 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1410 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1412 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1413 switch (funcdesc
->callconv
) {
1414 case CC_CDECL
: MESSAGE("cdecl");break;
1415 case CC_PASCAL
: MESSAGE("pascal");break;
1416 case CC_STDCALL
: MESSAGE("stdcall");break;
1417 case CC_SYSCALL
: MESSAGE("syscall");break;
1420 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1421 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1422 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1424 MESSAGE("\telemdescFunc (return value type):\n");
1425 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1428 static const char * const typekind_desc
[] =
1441 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1444 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1445 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1446 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1449 dump_FUNCDESC(&(pfd
->funcdesc
));
1451 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1452 if(pfd
->Entry
== NULL
)
1453 MESSAGE("\tentry: (null)\n");
1454 else if(pfd
->Entry
== (void*)-1)
1455 MESSAGE("\tentry: invalid\n");
1456 else if(IS_INTRESOURCE(pfd
->Entry
))
1457 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1459 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1461 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1465 dump_TLBFuncDescOne(pfd
);
1470 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1474 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1480 static void dump_TLBImpLib(const TLBImpLib
*import
)
1482 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1483 debugstr_w(import
->name
));
1484 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1485 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1488 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1492 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1494 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1495 if(ref
->index
== -1)
1496 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1498 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1500 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1502 TRACE_(typelib
)("in lib\n");
1503 dump_TLBImpLib(ref
->pImpTLInfo
);
1508 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1513 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1514 impl
->hRef
, impl
->implflags
);
1520 static void dump_DispParms(const DISPPARAMS
* pdp
)
1524 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1526 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1528 TRACE("named args:\n");
1529 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1530 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1533 if (pdp
->cArgs
&& pdp
->rgvarg
)
1536 for (index
= 0; index
< pdp
->cArgs
; index
++)
1537 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1541 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1543 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1544 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1545 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1546 TRACE("kind:%s\n", typekind_desc
[pty
->typeattr
.typekind
]);
1547 TRACE("fct:%u var:%u impl:%u\n", pty
->typeattr
.cFuncs
, pty
->typeattr
.cVars
, pty
->typeattr
.cImplTypes
);
1548 TRACE("wTypeFlags: 0x%04x\n", pty
->typeattr
.wTypeFlags
);
1549 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1550 if (pty
->typeattr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1552 dump_TLBFuncDesc(pty
->funcdescs
, pty
->typeattr
.cFuncs
);
1553 dump_TLBVarDesc(pty
->vardescs
, pty
->typeattr
.cVars
);
1554 dump_TLBImplType(pty
->impltypes
, pty
->typeattr
.cImplTypes
);
1557 static void dump_VARDESC(const VARDESC
*v
)
1559 MESSAGE("memid %d\n",v
->memid
);
1560 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1561 MESSAGE("oInst %d\n",v
->u
.oInst
);
1562 dump_ELEMDESC(&(v
->elemdescVar
));
1563 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1564 MESSAGE("varkind %d\n",v
->varkind
);
1567 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1569 /* VT_LPWSTR is largest type that, may appear in type description */
1570 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1571 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1572 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1573 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1574 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1575 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1576 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1577 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1580 static void TLB_abort(void)
1585 /* returns the size required for a deep copy of a typedesc into a
1587 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1591 if (alloc_initial_space
)
1592 size
+= sizeof(TYPEDESC
);
1598 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1601 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1602 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1608 /* deep copy a typedesc into a flat buffer */
1609 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1614 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1623 dest
->u
.lptdesc
= buffer
;
1624 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1627 dest
->u
.lpadesc
= buffer
;
1628 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1629 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1630 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1636 /* free custom data allocated by MSFT_CustData */
1637 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1639 TLBCustData
*cd
, *cdn
;
1640 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1642 list_remove(&cd
->entry
);
1643 VariantClear(&cd
->data
);
1648 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1653 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1654 ret
= SysAllocStringLen(NULL
, len
- 1);
1655 if (!ret
) return ret
;
1656 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1660 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(ITypeInfoImpl
*typeinfo
, MEMBERID memid
)
1664 for (i
= 0; i
< typeinfo
->typeattr
.cFuncs
; ++i
)
1666 if (typeinfo
->funcdescs
[i
].funcdesc
.memid
== memid
)
1667 return &typeinfo
->funcdescs
[i
];
1673 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid_invkind(ITypeInfoImpl
*typeinfo
, MEMBERID memid
, INVOKEKIND invkind
)
1677 for (i
= 0; i
< typeinfo
->typeattr
.cFuncs
; ++i
)
1679 if (typeinfo
->funcdescs
[i
].funcdesc
.memid
== memid
&& typeinfo
->funcdescs
[i
].funcdesc
.invkind
== invkind
)
1680 return &typeinfo
->funcdescs
[i
];
1686 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(ITypeInfoImpl
*typeinfo
, MEMBERID memid
)
1690 for (i
= 0; i
< typeinfo
->typeattr
.cVars
; ++i
)
1692 if (typeinfo
->vardescs
[i
].vardesc
.memid
== memid
)
1693 return &typeinfo
->vardescs
[i
];
1699 static inline TLBVarDesc
*TLB_get_vardesc_by_name(ITypeInfoImpl
*typeinfo
, const OLECHAR
*name
)
1703 for (i
= 0; i
< typeinfo
->typeattr
.cVars
; ++i
)
1705 if (!lstrcmpiW(TLB_get_bstr(typeinfo
->vardescs
[i
].Name
), name
))
1706 return &typeinfo
->vardescs
[i
];
1712 static inline TLBCustData
*TLB_get_custdata_by_guid(const struct list
*custdata_list
, REFGUID guid
)
1714 TLBCustData
*cust_data
;
1715 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1716 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1721 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeLibImpl
*typelib
, const OLECHAR
*name
)
1725 for (i
= 0; i
< typelib
->TypeInfoCount
; ++i
)
1727 if (!lstrcmpiW(TLB_get_bstr(typelib
->typeinfos
[i
]->Name
), name
))
1728 return typelib
->typeinfos
[i
];
1734 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1736 list_init(&var_desc
->custdata_list
);
1739 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1743 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1748 TLBVarDesc_Constructor(&ret
[n
-1]);
1755 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1759 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1764 list_init(&ret
[n
-1].custdata_list
);
1771 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1773 list_init(&func_desc
->custdata_list
);
1776 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1780 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1785 TLBFuncDesc_Constructor(&ret
[n
-1]);
1792 static void TLBImplType_Constructor(TLBImplType
*impl
)
1794 list_init(&impl
->custdata_list
);
1797 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1801 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1806 TLBImplType_Constructor(&ret
[n
-1]);
1813 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1814 const GUID
*new_guid
, HREFTYPE hreftype
)
1818 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1819 if (IsEqualGUID(&guid
->guid
, new_guid
))
1823 guid
= heap_alloc(sizeof(TLBGuid
));
1827 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1828 guid
->hreftype
= hreftype
;
1830 list_add_tail(guid_list
, &guid
->entry
);
1835 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1837 TLBCustData
*cust_data
;
1849 return DISP_E_BADVARTYPE
;
1852 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1855 cust_data
= heap_alloc(sizeof(TLBCustData
));
1857 return E_OUTOFMEMORY
;
1859 cust_data
->guid
= tlbguid
;
1860 VariantInit(&cust_data
->data
);
1862 list_add_tail(custdata_list
, &cust_data
->entry
);
1864 VariantClear(&cust_data
->data
);
1866 return VariantCopy(&cust_data
->data
, var
);
1869 /* Used to update list pointers after list itself was moved. */
1870 static void TLB_relink_custdata(struct list
*custdata_list
)
1872 if (custdata_list
->prev
== custdata_list
->next
)
1873 list_init(custdata_list
);
1876 custdata_list
->prev
->next
= custdata_list
;
1877 custdata_list
->next
->prev
= custdata_list
;
1881 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1888 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1889 if (wcscmp(str
->str
, new_str
) == 0)
1893 str
= heap_alloc(sizeof(TLBString
));
1897 str
->str
= SysAllocString(new_str
);
1903 list_add_tail(string_list
, &str
->entry
);
1908 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1909 ULONG
*size
, WORD
*align
)
1915 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1919 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1921 ITypeInfo_Release(other
);
1926 *size
= attr
->cbSizeInstance
;
1928 *align
= attr
->cbAlignment
;
1930 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1931 ITypeInfo_Release(other
);
1936 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1937 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1939 ULONG i
, sub
, ptr_size
;
1942 ptr_size
= get_ptr_size(sys
);
1981 *size
= sizeof(DATE
);
1984 *size
= sizeof(VARIANT
);
1986 if(sys
== SYS_WIN32
)
1987 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1991 *size
= sizeof(DECIMAL
);
1998 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
1999 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2000 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2005 case VT_USERDEFINED
:
2006 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2008 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2022 /**********************************************************************
2024 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2027 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2029 if (where
!= DO_NOT_SEEK
)
2031 where
+= pcx
->oStart
;
2032 if (where
> pcx
->length
)
2035 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2043 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2045 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2046 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2048 MSFT_Seek(pcx
, where
);
2049 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2050 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2055 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2060 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2061 FromLEDWords(buffer
, ret
);
2066 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2071 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2072 FromLEWords(buffer
, ret
);
2077 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2080 MSFT_GuidEntry entry
;
2083 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2085 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2088 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2090 guid
= heap_alloc(sizeof(TLBGuid
));
2092 guid
->offset
= offs
;
2093 guid
->guid
= entry
.guid
;
2094 guid
->hreftype
= entry
.hreftype
;
2096 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2098 offs
+= sizeof(MSFT_GuidEntry
);
2102 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2106 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2107 if(ret
->offset
== offset
){
2108 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2116 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2118 MSFT_NameIntro niName
;
2122 ERR_(typelib
)("bad offset %d\n", offset
);
2126 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2127 pcx
->pTblDir
->pNametab
.offset
+offset
);
2129 return niName
.hreftype
;
2132 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2135 MSFT_NameIntro intro
;
2137 int offs
= 0, lengthInChars
;
2139 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2143 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2146 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2147 intro
.namelen
&= 0xFF;
2148 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2150 len_piece
= (len_piece
+ 4) & ~0x3;
2154 string
= heap_alloc(len_piece
+ 1);
2155 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2156 string
[intro
.namelen
] = '\0';
2158 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2159 string
, -1, NULL
, 0);
2160 if (!lengthInChars
) {
2162 return E_UNEXPECTED
;
2165 tlbstr
= heap_alloc(sizeof(TLBString
));
2167 tlbstr
->offset
= offs
;
2168 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2169 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2173 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2179 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2183 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2184 if (tlbstr
->offset
== offset
) {
2185 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2193 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2197 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2198 if (tlbstr
->offset
== offset
) {
2199 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2208 * read a value and fill a VARIANT structure
2210 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2214 TRACE_(typelib
)("\n");
2216 if(offset
<0) { /* data are packed in here */
2217 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2218 V_I4(pVar
) = offset
& 0x3ffffff;
2221 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2222 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2223 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2224 switch (V_VT(pVar
)){
2225 case VT_EMPTY
: /* FIXME: is this right? */
2226 case VT_NULL
: /* FIXME: is this right? */
2227 case VT_I2
: /* this should not happen */
2238 case VT_VOID
: /* FIXME: is this right? */
2246 case VT_DECIMAL
: /* FIXME: is this right? */
2249 /* pointer types with known behaviour */
2252 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2254 V_BSTR(pVar
) = NULL
;
2256 ptr
= heap_alloc_zero(size
);
2257 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2258 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2259 /* FIXME: do we need a AtoW conversion here? */
2260 V_UNION(pVar
, bstrVal
[size
])='\0';
2261 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2266 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2273 case VT_USERDEFINED
:
2279 case VT_STREAMED_OBJECT
:
2280 case VT_STORED_OBJECT
:
2281 case VT_BLOB_OBJECT
:
2286 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2290 if(size
>0) /* (big|small) endian correct? */
2291 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2295 * create a linked list with custom data
2297 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2303 TRACE_(typelib
)("\n");
2305 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2309 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2310 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2311 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2312 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2313 list_add_head(custdata_list
, &pNew
->entry
);
2314 offset
= entry
.next
;
2319 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2322 pTd
->vt
=type
& VT_TYPEMASK
;
2324 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2326 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2329 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2331 return (invkind
== INVOKE_PROPERTYGET
||
2332 invkind
== INVOKE_PROPERTYPUT
||
2333 invkind
== INVOKE_PROPERTYPUTREF
);
2337 MSFT_DoFuncs(TLBContext
* pcx
,
2342 TLBFuncDesc
** pptfd
)
2345 * member information is stored in a data structure at offset
2346 * indicated by the memoffset field of the typeinfo structure
2347 * There are several distinctive parts.
2348 * The first part starts with a field that holds the total length
2349 * of this (first) part excluding this field. Then follow the records,
2350 * for each member there is one record.
2352 * The first entry is always the length of the record (including this
2354 * The rest of the record depends on the type of the member. If there is
2355 * a field indicating the member type (function, variable, interface, etc)
2356 * I have not found it yet. At this time we depend on the information
2357 * in the type info and the usual order how things are stored.
2359 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2362 * Third is an equal sized array with file offsets to the name entry
2365 * The fourth and last (?) part is an array with offsets to the records
2366 * in the first part of this file segment.
2369 int infolen
, nameoffset
, reclength
, i
;
2370 int recoffset
= offset
+ sizeof(INT
);
2372 char *recbuf
= heap_alloc(0xffff);
2373 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2374 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2376 TRACE_(typelib
)("\n");
2378 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2380 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2382 for ( i
= 0; i
< cFuncs
; i
++ )
2386 /* name, eventually add to a hash table */
2387 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2388 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2390 /* read the function information record */
2391 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2393 reclength
&= 0xffff;
2395 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2397 /* size without argument data */
2398 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2399 if (pFuncRec
->FKCCIC
& 0x1000)
2400 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2402 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2403 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2405 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2406 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2408 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2410 if (pFuncRec
->FKCCIC
& 0x2000 )
2412 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2413 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2414 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2417 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2420 ptfd
->Entry
= (TLBString
*)-1;
2422 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2423 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2425 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2426 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2428 /* fill the FuncDesc Structure */
2429 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2430 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2432 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2433 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2434 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2435 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2436 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2437 if (ptfd
->funcdesc
.funckind
== FUNC_DISPATCH
)
2438 ptfd
->funcdesc
.oVft
= 0;
2440 ptfd
->funcdesc
.oVft
= (pFuncRec
->VtableOffset
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
2441 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2443 /* nameoffset is sometimes -1 on the second half of a propget/propput
2444 * pair of functions */
2445 if ((nameoffset
== -1) && (i
> 0) &&
2446 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2447 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2448 ptfd
->Name
= ptfd_prev
->Name
;
2450 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2454 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2456 /* do the parameters/arguments */
2457 if(pFuncRec
->nrargs
)
2460 MSFT_ParameterInfo paraminfo
;
2462 ptfd
->funcdesc
.lprgelemdescParam
=
2463 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2465 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2467 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2468 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2470 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2472 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2478 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2481 if (paraminfo
.oName
!= -1)
2482 ptfd
->pParamDesc
[j
].Name
=
2483 MSFT_ReadName( pcx
, paraminfo
.oName
);
2484 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2487 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2488 (pFuncRec
->FKCCIC
& 0x1000) )
2490 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2492 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2494 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2496 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2497 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2499 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2503 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2506 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2507 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2508 pFuncRec
->FKCCIC
& 0x80 )
2511 pFuncRec
->oArgCustData
[j
],
2512 &ptfd
->pParamDesc
[j
].custdata_list
);
2515 /* SEEK value = jump to offset,
2516 * from there jump to the end of record,
2517 * go back by (j-1) arguments
2519 MSFT_ReadLEDWords( ¶minfo
,
2520 sizeof(MSFT_ParameterInfo
), pcx
,
2521 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2522 * sizeof(MSFT_ParameterInfo
)));
2526 /* scode is not used: archaic win16 stuff FIXME: right? */
2527 ptfd
->funcdesc
.cScodes
= 0 ;
2528 ptfd
->funcdesc
.lprgscode
= NULL
;
2532 recoffset
+= reclength
;
2537 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2538 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2540 int infolen
, nameoffset
, reclength
;
2542 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2547 TRACE_(typelib
)("\n");
2549 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2550 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2551 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2552 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2553 recoffset
+= offset
+sizeof(INT
);
2554 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2555 /* name, eventually add to a hash table */
2556 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2557 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2558 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2559 /* read the variable information record */
2560 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2562 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2565 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2566 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2568 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2569 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2571 if (reclength
> FIELD_OFFSET(MSFT_VarRecord
, oCustData
))
2572 MSFT_CustData(pcx
, pVarRec
->oCustData
, &ptvd
->custdata_list
);
2574 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2575 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2577 /* fill the VarDesc Structure */
2578 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2579 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2580 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2581 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2582 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2583 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2584 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2585 if(pVarRec
->VarKind
== VAR_CONST
){
2586 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2587 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2588 pVarRec
->OffsValue
, pcx
);
2590 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2591 recoffset
+= reclength
;
2595 /* process Implemented Interfaces of a com class */
2596 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2600 MSFT_RefRecord refrec
;
2603 TRACE_(typelib
)("\n");
2605 pTI
->impltypes
= TLBImplType_Alloc(count
);
2606 pImpl
= pTI
->impltypes
;
2607 for(i
=0;i
<count
;i
++){
2608 if(offset
<0) break; /* paranoia */
2609 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2610 pImpl
->hRef
= refrec
.reftype
;
2611 pImpl
->implflags
=refrec
.flags
;
2612 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2613 offset
=refrec
.onext
;
2619 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2620 * and some structures, and fix the alignment */
2621 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2623 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2624 switch(info
->tdescAlias
->vt
){
2632 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2633 info
->typeattr
.cbAlignment
= sizeof(void*);
2636 case VT_USERDEFINED
:
2637 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2640 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2641 info
->typeattr
.cbAlignment
= 8;
2643 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2644 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2646 info
->typeattr
.cbAlignment
= sizeof(void*);
2649 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2650 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2651 info
->typeattr
.typekind
== TKIND_COCLASS
){
2652 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2653 info
->typeattr
.cbAlignment
= sizeof(void*);
2659 * process a typeinfo record
2661 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2664 ITypeLibImpl
* pLibInfo
)
2666 MSFT_TypeInfoBase tiBase
;
2667 ITypeInfoImpl
*ptiRet
;
2669 TRACE_(typelib
)("count=%u\n", count
);
2671 ptiRet
= ITypeInfoImpl_Constructor();
2672 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2673 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2675 /* this is where we are coming from */
2676 ptiRet
->pTypeLib
= pLibInfo
;
2677 ptiRet
->index
=count
;
2679 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2680 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2681 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2682 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2683 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2684 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2685 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2686 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2687 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2688 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2689 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2690 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2691 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
;
2692 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2694 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2695 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2696 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2700 /* IDLDESC idldescType; *//* never saw this one != zero */
2702 /* name, eventually add to a hash table */
2703 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2704 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2705 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2707 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2708 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2709 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2711 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2712 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2714 /* note: InfoType's Help file and HelpStringDll come from the containing
2715 * library. Further HelpString and Docstring appear to be the same thing :(
2718 if(ptiRet
->typeattr
.cFuncs
>0 )
2719 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2720 ptiRet
->typeattr
.cVars
,
2721 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2723 if(ptiRet
->typeattr
.cVars
>0 )
2724 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2725 ptiRet
->typeattr
.cVars
,
2726 tiBase
.memoffset
, &ptiRet
->vardescs
);
2727 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2728 switch(ptiRet
->typeattr
.typekind
)
2731 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2734 case TKIND_DISPATCH
:
2735 /* This is not -1 when the interface is a non-base dual interface or
2736 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2737 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2741 if (tiBase
.datatype1
!= -1)
2743 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2744 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2748 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2749 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2753 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2755 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2756 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2757 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2758 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2759 if (TRACE_ON(typelib
))
2760 dump_TypeInfo(ptiRet
);
2765 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2768 INT16 len_str
, len_piece
;
2769 int offs
= 0, lengthInChars
;
2771 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2775 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2778 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2779 len_piece
= len_str
+ sizeof(INT16
);
2781 len_piece
= (len_piece
+ 4) & ~0x3;
2785 string
= heap_alloc(len_piece
+ 1);
2786 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2787 string
[len_str
] = '\0';
2789 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2790 string
, -1, NULL
, 0);
2791 if (!lengthInChars
) {
2793 return E_UNEXPECTED
;
2796 tlbstr
= heap_alloc(sizeof(TLBString
));
2798 tlbstr
->offset
= offs
;
2799 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2800 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2804 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2810 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2815 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2816 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2817 MSFT_ImpInfo impinfo
;
2820 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2822 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2823 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2825 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2826 if(pImpLib
->offset
==impinfo
.oImpFile
)
2829 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2830 ref
->reference
= offs
;
2831 ref
->pImpTLInfo
= pImpLib
;
2832 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2833 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2834 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2835 ref
->index
= TLB_REF_USE_GUID
;
2837 ref
->index
= impinfo
.oGuid
;
2839 ERR("Cannot find a reference\n");
2840 ref
->reference
= -1;
2841 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2844 offs
+= sizeof(impinfo
);
2850 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2851 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2852 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2855 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2856 static CRITICAL_SECTION cache_section
;
2857 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2859 0, 0, &cache_section
,
2860 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2861 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2863 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2866 typedef struct TLB_PEFile
2868 IUnknown IUnknown_iface
;
2871 HRSRC typelib_resource
;
2872 HGLOBAL typelib_global
;
2873 LPVOID typelib_base
;
2876 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2878 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2881 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2883 if (IsEqualIID(riid
, &IID_IUnknown
))
2886 IUnknown_AddRef(iface
);
2890 return E_NOINTERFACE
;
2893 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2895 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2896 return InterlockedIncrement(&This
->refs
);
2899 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2901 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2902 ULONG refs
= InterlockedDecrement(&This
->refs
);
2905 if (This
->typelib_global
)
2906 FreeResource(This
->typelib_global
);
2908 FreeLibrary(This
->dll
);
2914 static const IUnknownVtbl TLB_PEFile_Vtable
=
2916 TLB_PEFile_QueryInterface
,
2921 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2924 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2926 This
= heap_alloc(sizeof(TLB_PEFile
));
2928 return E_OUTOFMEMORY
;
2930 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2933 This
->typelib_resource
= NULL
;
2934 This
->typelib_global
= NULL
;
2935 This
->typelib_base
= NULL
;
2937 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2938 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2942 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), L
"TYPELIB");
2943 if (This
->typelib_resource
)
2945 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2946 if (This
->typelib_global
)
2948 This
->typelib_base
= LockResource(This
->typelib_global
);
2950 if (This
->typelib_base
)
2952 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2953 *ppBase
= This
->typelib_base
;
2954 *ppFile
= &This
->IUnknown_iface
;
2960 TRACE("No TYPELIB resource found\n");
2964 TLB_PEFile_Release(&This
->IUnknown_iface
);
2968 typedef struct TLB_NEFile
2970 IUnknown IUnknown_iface
;
2972 LPVOID typelib_base
;
2975 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2977 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2980 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2982 if (IsEqualIID(riid
, &IID_IUnknown
))
2985 IUnknown_AddRef(iface
);
2989 return E_NOINTERFACE
;
2992 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2994 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2995 return InterlockedIncrement(&This
->refs
);
2998 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
3000 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3001 ULONG refs
= InterlockedDecrement(&This
->refs
);
3004 heap_free(This
->typelib_base
);
3010 static const IUnknownVtbl TLB_NEFile_Vtable
=
3012 TLB_NEFile_QueryInterface
,
3017 /***********************************************************************
3018 * read_xx_header [internal]
3020 static int read_xx_header( HFILE lzfd
)
3022 IMAGE_DOS_HEADER mzh
;
3025 LZSeek( lzfd
, 0, SEEK_SET
);
3026 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3028 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3031 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3032 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3035 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3037 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3038 return IMAGE_OS2_SIGNATURE
;
3039 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3040 return IMAGE_NT_SIGNATURE
;
3043 WARN("Can't handle %s files.\n", magic
);
3048 /***********************************************************************
3049 * find_ne_resource [internal]
3051 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3052 DWORD
*resLen
, DWORD
*resOff
)
3054 IMAGE_OS2_HEADER nehd
;
3055 NE_TYPEINFO
*typeInfo
;
3056 NE_NAMEINFO
*nameInfo
;
3062 /* Read in NE header */
3063 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3064 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3066 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3069 TRACE("No resources in NE dll\n" );
3073 /* Read in resource table */
3074 resTab
= heap_alloc( resTabSize
);
3075 if ( !resTab
) return FALSE
;
3077 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3078 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3080 heap_free( resTab
);
3085 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3087 if (!IS_INTRESOURCE(typeid)) /* named type */
3089 BYTE len
= strlen( typeid );
3090 while (typeInfo
->type_id
)
3092 if (!(typeInfo
->type_id
& 0x8000))
3094 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3095 if ((*p
== len
) && !_strnicmp( (char*)p
+1, typeid, len
)) goto found_type
;
3097 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3098 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3101 else /* numeric type id */
3103 WORD id
= LOWORD(typeid) | 0x8000;
3104 while (typeInfo
->type_id
)
3106 if (typeInfo
->type_id
== id
) goto found_type
;
3107 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3108 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3111 TRACE("No typeid entry found for %p\n", typeid );
3112 heap_free( resTab
);
3116 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3118 if (!IS_INTRESOURCE(resid
)) /* named resource */
3120 BYTE len
= strlen( resid
);
3121 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3123 BYTE
*p
= resTab
+ nameInfo
->id
;
3124 if (nameInfo
->id
& 0x8000) continue;
3125 if ((*p
== len
) && !_strnicmp( (char*)p
+1, resid
, len
)) goto found_name
;
3128 else /* numeric resource id */
3130 WORD id
= LOWORD(resid
) | 0x8000;
3131 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3132 if (nameInfo
->id
== id
) goto found_name
;
3134 TRACE("No resid entry found for %p\n", typeid );
3135 heap_free( resTab
);
3139 /* Return resource data */
3140 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3141 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3143 heap_free( resTab
);
3147 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3151 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3154 This
= heap_alloc(sizeof(TLB_NEFile
));
3155 if (!This
) return E_OUTOFMEMORY
;
3157 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3159 This
->typelib_base
= NULL
;
3161 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3162 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3164 DWORD reslen
, offset
;
3165 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3167 This
->typelib_base
= heap_alloc(reslen
);
3168 if( !This
->typelib_base
)
3172 LZSeek( lzfd
, offset
, SEEK_SET
);
3173 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3175 *ppBase
= This
->typelib_base
;
3176 *pdwTLBLength
= reslen
;
3177 *ppFile
= &This
->IUnknown_iface
;
3183 if( lzfd
>= 0) LZClose( lzfd
);
3184 TLB_NEFile_Release(&This
->IUnknown_iface
);
3188 typedef struct TLB_Mapping
3190 IUnknown IUnknown_iface
;
3194 LPVOID typelib_base
;
3197 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3199 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3202 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3204 if (IsEqualIID(riid
, &IID_IUnknown
))
3207 IUnknown_AddRef(iface
);
3211 return E_NOINTERFACE
;
3214 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3216 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3217 return InterlockedIncrement(&This
->refs
);
3220 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3222 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3223 ULONG refs
= InterlockedDecrement(&This
->refs
);
3226 if (This
->typelib_base
)
3227 UnmapViewOfFile(This
->typelib_base
);
3229 CloseHandle(This
->mapping
);
3230 if (This
->file
!= INVALID_HANDLE_VALUE
)
3231 CloseHandle(This
->file
);
3237 static const IUnknownVtbl TLB_Mapping_Vtable
=
3239 TLB_Mapping_QueryInterface
,
3244 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3248 This
= heap_alloc(sizeof(TLB_Mapping
));
3250 return E_OUTOFMEMORY
;
3252 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3254 This
->file
= INVALID_HANDLE_VALUE
;
3255 This
->mapping
= NULL
;
3256 This
->typelib_base
= NULL
;
3258 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3259 if (INVALID_HANDLE_VALUE
!= This
->file
)
3261 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3264 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3265 if(This
->typelib_base
)
3267 /* retrieve file size */
3268 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3269 *ppBase
= This
->typelib_base
;
3270 *ppFile
= &This
->IUnknown_iface
;
3276 IUnknown_Release(&This
->IUnknown_iface
);
3277 return TYPE_E_CANTLOADLIBRARY
;
3280 /****************************************************************************
3283 * find the type of the typelib file and map the typelib resource into
3287 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3288 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3290 ITypeLibImpl
*entry
;
3293 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3294 LPVOID pBase
= NULL
;
3295 DWORD dwTLBLength
= 0;
3296 IUnknown
*pFile
= NULL
;
3301 index_str
= wcsrchr(pszFileName
, '\\');
3302 if(index_str
&& *++index_str
!= '\0')
3305 LONG idx
= wcstol(index_str
, &end_ptr
, 10);
3306 if(*end_ptr
== '\0')
3308 int str_len
= index_str
- pszFileName
- 1;
3310 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3311 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3316 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3318 if(wcschr(file
, '\\'))
3320 lstrcpyW(pszPath
, file
);
3324 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3325 pszPath
[len
] = '\\';
3326 memcpy(pszPath
+ len
+ 1, file
, (lstrlenW(file
) + 1) * sizeof(WCHAR
));
3330 if(file
!= pszFileName
) heap_free(file
);
3332 h
= CreateFileW(pszPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3333 if(h
!= INVALID_HANDLE_VALUE
){
3334 GetFinalPathNameByHandleW(h
, pszPath
, cchPath
, FILE_NAME_NORMALIZED
| VOLUME_NAME_DOS
);
3338 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3340 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3341 EnterCriticalSection(&cache_section
);
3342 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3344 if (!wcsicmp(entry
->path
, pszPath
) && entry
->index
== index
)
3346 TRACE("cache hit\n");
3347 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3348 ITypeLib2_AddRef(*ppTypeLib
);
3349 LeaveCriticalSection(&cache_section
);
3353 LeaveCriticalSection(&cache_section
);
3355 /* now actually load and parse the typelib */
3357 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3358 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3359 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3360 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3361 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3364 if (dwTLBLength
>= 4)
3366 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3367 if (dwSignature
== MSFT_SIGNATURE
)
3368 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3369 else if (dwSignature
== SLTG_SIGNATURE
)
3370 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3373 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3374 ret
= TYPE_E_CANTLOADLIBRARY
;
3378 ret
= TYPE_E_CANTLOADLIBRARY
;
3379 IUnknown_Release(pFile
);
3383 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3385 TRACE("adding to cache\n");
3386 impl
->path
= heap_alloc((lstrlenW(pszPath
)+1) * sizeof(WCHAR
));
3387 lstrcpyW(impl
->path
, pszPath
);
3388 /* We should really canonicalise the path here. */
3389 impl
->index
= index
;
3391 /* FIXME: check if it has added already in the meantime */
3392 EnterCriticalSection(&cache_section
);
3393 list_add_head(&tlb_cache
, &impl
->entry
);
3394 LeaveCriticalSection(&cache_section
);
3400 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3402 ret
= TYPE_E_CANTLOADLIBRARY
;
3409 /*================== ITypeLib(2) Methods ===================================*/
3411 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3413 ITypeLibImpl
* pTypeLibImpl
;
3415 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3416 if (!pTypeLibImpl
) return NULL
;
3418 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3419 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3420 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3421 pTypeLibImpl
->ref
= 1;
3423 list_init(&pTypeLibImpl
->implib_list
);
3424 list_init(&pTypeLibImpl
->custdata_list
);
3425 list_init(&pTypeLibImpl
->name_list
);
3426 list_init(&pTypeLibImpl
->string_list
);
3427 list_init(&pTypeLibImpl
->guid_list
);
3428 list_init(&pTypeLibImpl
->ref_list
);
3429 pTypeLibImpl
->dispatch_href
= -1;
3431 return pTypeLibImpl
;
3434 /****************************************************************************
3435 * ITypeLib2_Constructor_MSFT
3437 * loading an MSFT typelib from an in-memory image
3439 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3443 MSFT_Header tlbHeader
;
3444 MSFT_SegDir tlbSegDir
;
3445 ITypeLibImpl
* pTypeLibImpl
;
3448 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3450 pTypeLibImpl
= TypeLibImpl_Constructor();
3451 if (!pTypeLibImpl
) return NULL
;
3453 /* get pointer to beginning of typelib data */
3457 cx
.pLibInfo
= pTypeLibImpl
;
3458 cx
.length
= dwTLBLength
;
3461 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3462 TRACE_(typelib
)("header:\n");
3463 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3464 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3465 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3468 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3470 /* there is a small amount of information here until the next important
3472 * the segment directory . Try to calculate the amount of data */
3473 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3475 /* now read the segment directory */
3476 TRACE("read segment directory (at %d)\n",lPSegDir
);
3477 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3478 cx
.pTblDir
= &tlbSegDir
;
3480 /* just check two entries */
3481 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3483 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3484 heap_free(pTypeLibImpl
);
3488 MSFT_ReadAllNames(&cx
);
3489 MSFT_ReadAllStrings(&cx
);
3490 MSFT_ReadAllGuids(&cx
);
3492 /* now fill our internal data */
3493 /* TLIBATTR fields */
3494 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3496 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3497 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3498 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3499 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3500 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3502 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3503 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3505 /* name, eventually add to a hash table */
3506 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3509 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3510 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3512 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3515 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3516 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3519 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3522 if(tlbHeader
.CustomDataOffset
>= 0)
3524 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3527 /* fill in type descriptions */
3528 if(tlbSegDir
.pTypdescTab
.length
> 0)
3530 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3532 pTypeLibImpl
->ctTypeDesc
= cTD
;
3533 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3534 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3537 /* FIXME: add several sanity checks here */
3538 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3539 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3541 /* FIXME: check safearray */
3543 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3545 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3547 else if(td
[0] == VT_CARRAY
)
3549 /* array descr table here */
3550 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3552 else if(td
[0] == VT_USERDEFINED
)
3554 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3556 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3559 /* second time around to fill the array subscript info */
3562 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3563 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3565 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3566 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3569 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3571 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3573 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3575 for(j
= 0; j
<td
[2]; j
++)
3577 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3578 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3579 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3580 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3585 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3586 ERR("didn't find array description data\n");
3591 /* imported type libs */
3592 if(tlbSegDir
.pImpFiles
.offset
>0)
3595 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3598 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3602 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3603 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3604 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3606 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3607 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3608 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3609 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3612 name
= heap_alloc_zero(size
+1);
3613 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3614 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3617 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3618 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3620 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3624 MSFT_ReadAllRefs(&cx
);
3626 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3629 if(tlbHeader
.nrtypeinfos
>= 0 )
3631 ITypeInfoImpl
**ppTI
;
3633 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3635 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3637 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3640 (pTypeLibImpl
->TypeInfoCount
)++;
3645 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3646 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3647 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3651 TRACE("(%p)\n", pTypeLibImpl
);
3652 return &pTypeLibImpl
->ITypeLib2_iface
;
3656 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3662 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3663 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3667 guid
->Data4
[0] = s
>> 8;
3668 guid
->Data4
[1] = s
& 0xff;
3671 for(i
= 0; i
< 6; i
++) {
3672 memcpy(b
, str
+ 24 + 2 * i
, 2);
3673 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3678 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3685 bytelen
= *(const WORD
*)ptr
;
3686 if(bytelen
== 0xffff) return 2;
3688 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3689 tmp_str
= SysAllocStringLen(NULL
, len
);
3691 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3692 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3693 SysFreeString(tmp_str
);
3698 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3703 bytelen
= *(const WORD
*)ptr
;
3704 if(bytelen
== 0xffff) return 2;
3705 *str
= heap_alloc(bytelen
+ 1);
3706 memcpy(*str
, ptr
+ 2, bytelen
);
3707 (*str
)[bytelen
] = '\0';
3711 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3716 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3717 if (tlbstr
->offset
== offset
)
3721 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3722 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3723 SysFreeString(tmp_str
);
3728 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3730 char *ptr
= pLibBlk
;
3733 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3734 FIXME("libblk magic = %04x\n", w
);
3739 if((w
= *(WORD
*)ptr
) != 0xffff) {
3740 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w
);
3745 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3747 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3749 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3752 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3753 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3756 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3757 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3759 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3762 ptr
+= 4; /* skip res12 */
3764 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3767 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3770 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3773 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3774 ptr
+= sizeof(GUID
);
3776 return ptr
- (char*)pLibBlk
;
3779 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3784 } sltg_ref_lookup_t
;
3786 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3787 HREFTYPE
*typelib_ref
)
3789 if(table
&& typeinfo_ref
< table
->num
)
3791 *typelib_ref
= table
->refs
[typeinfo_ref
];
3795 ERR_(typelib
)("Unable to find reference\n");
3800 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3805 if((*pType
& 0xe00) == 0xe00) {
3807 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3808 pTD
= pTD
->u
.lptdesc
;
3810 switch(*pType
& 0x3f) {
3813 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3814 pTD
= pTD
->u
.lptdesc
;
3817 case VT_USERDEFINED
:
3818 pTD
->vt
= VT_USERDEFINED
;
3819 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3825 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3828 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3830 pTD
->vt
= VT_CARRAY
;
3831 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3832 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3833 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3834 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3836 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3842 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3846 pTD
->vt
= VT_SAFEARRAY
;
3847 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3848 pTD
= pTD
->u
.lptdesc
;
3852 pTD
->vt
= *pType
& 0x3f;
3861 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3862 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3864 /* Handle [in/out] first */
3865 if((*pType
& 0xc000) == 0xc000)
3866 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3867 else if(*pType
& 0x8000)
3868 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3869 else if(*pType
& 0x4000)
3870 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3872 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3875 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3878 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3880 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3884 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3889 TLBRefType
*ref_type
;
3890 sltg_ref_lookup_t
*table
;
3891 HREFTYPE typelib_ref
;
3893 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3894 FIXME("Ref magic = %x\n", pRef
->magic
);
3897 name
= ( (char*)pRef
->names
+ pRef
->number
);
3899 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3900 table
->num
= pRef
->number
>> 3;
3902 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3904 /* We don't want the first href to be 0 */
3905 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3907 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3909 unsigned int lib_offs
, type_num
;
3911 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3913 name
+= SLTG_ReadStringA(name
, &refname
);
3914 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3915 FIXME_(typelib
)("Can't sscanf ref\n");
3916 if(lib_offs
!= 0xffff) {
3919 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3920 if(import
->offset
== lib_offs
)
3923 if(&import
->entry
== &pTL
->implib_list
) {
3924 char fname
[MAX_PATH
+1];
3928 import
= heap_alloc_zero(sizeof(*import
));
3929 import
->offset
= lib_offs
;
3930 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3931 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3932 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3933 &import
->wVersionMajor
,
3934 &import
->wVersionMinor
,
3935 &import
->lcid
, fname
) != 4) {
3936 FIXME_(typelib
)("can't sscanf ref %s\n",
3937 pNameTable
+ lib_offs
+ 40);
3939 len
= strlen(fname
);
3940 if(fname
[len
-1] != '#')
3941 FIXME("fname = %s\n", fname
);
3942 fname
[len
-1] = '\0';
3943 import
->name
= TLB_MultiByteToBSTR(fname
);
3944 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3946 ref_type
->pImpTLInfo
= import
;
3948 /* Store a reference to IDispatch */
3949 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3950 pTL
->dispatch_href
= typelib_ref
;
3952 } else { /* internal ref */
3953 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3955 ref_type
->reference
= typelib_ref
;
3956 ref_type
->index
= type_num
;
3959 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3961 table
->refs
[ref
] = typelib_ref
;
3964 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3965 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3966 dump_TLBRefType(pTL
);
3970 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3971 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3973 SLTG_ImplInfo
*info
;
3974 TLBImplType
*pImplType
;
3975 /* I don't really get this structure, usually it's 0x16 bytes
3976 long, but iuser.tlb contains some that are 0x18 bytes long.
3977 That's ok because we can use the next ptr to jump to the next
3978 one. But how do we know the length of the last one? The WORD
3979 at offs 0x8 might be the clue. For now I'm just assuming that
3980 the last one is the regular 0x16 bytes. */
3982 info
= (SLTG_ImplInfo
*)pBlk
;
3984 pTI
->typeattr
.cImplTypes
++;
3985 if(info
->next
== 0xffff)
3987 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3990 info
= (SLTG_ImplInfo
*)pBlk
;
3991 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
3992 pImplType
= pTI
->impltypes
;
3994 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3995 pImplType
->implflags
= info
->impltypeflags
;
3998 if(info
->next
== 0xffff)
4001 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4002 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4004 info
++; /* see comment at top of function */
4008 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4009 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4011 TLBVarDesc
*pVarDesc
;
4012 const TLBString
*prevName
= NULL
;
4013 SLTG_Variable
*pItem
;
4017 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4019 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4020 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4022 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4024 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4025 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4026 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4030 if (pItem
->name
== 0xfffe)
4031 pVarDesc
->Name
= prevName
;
4033 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4035 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4036 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4037 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4039 if(pItem
->flags
& 0x02)
4040 pType
= &pItem
->type
;
4042 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4044 if (pItem
->flags
& ~0xda)
4045 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4047 SLTG_DoElem(pType
, pBlk
,
4048 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4050 if (TRACE_ON(typelib
)) {
4052 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4053 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4056 if (pItem
->flags
& 0x40) {
4057 TRACE_(typelib
)("VAR_DISPATCH\n");
4058 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4060 else if (pItem
->flags
& 0x10) {
4061 TRACE_(typelib
)("VAR_CONST\n");
4062 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4063 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4064 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4065 if (pItem
->flags
& 0x08)
4066 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4068 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4074 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4076 TRACE_(typelib
)("len = %u\n", len
);
4077 if (len
== 0xffff) {
4080 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4081 str
= SysAllocStringLen(NULL
, alloc_len
);
4082 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4084 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4085 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4094 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4095 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4098 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4103 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4104 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4105 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4108 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4109 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4111 if (pItem
->flags
& 0x80)
4112 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4114 prevName
= pVarDesc
->Name
;
4116 pTI
->typeattr
.cVars
= cVars
;
4119 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4120 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4122 SLTG_Function
*pFunc
;
4124 TLBFuncDesc
*pFuncDesc
;
4126 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4128 pFuncDesc
= pTI
->funcdescs
;
4129 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4130 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4135 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4136 case SLTG_FUNCTION_MAGIC
:
4137 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4139 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4140 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4142 case SLTG_STATIC_FUNCTION_MAGIC
:
4143 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4146 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4149 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4151 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4152 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4153 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4154 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4155 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4156 if (pFuncDesc
->funcdesc
.funckind
== FUNC_DISPATCH
)
4157 pFuncDesc
->funcdesc
.oVft
= 0;
4159 pFuncDesc
->funcdesc
.oVft
= (pFunc
->vtblpos
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
4161 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4162 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4164 if(pFunc
->retnextopt
& 0x80)
4165 pType
= &pFunc
->rettype
;
4167 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4169 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4171 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4172 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4173 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4175 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4177 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4178 char *paramName
= pNameTable
+ *pArg
;
4180 /* If arg type follows then paramName points to the 2nd
4181 letter of the name, else the next WORD is an offset to
4182 the arg type and paramName points to the first letter.
4183 So let's take one char off paramName and see if we're
4184 pointing at an alphanumeric char. However if *pArg is
4185 0xffff or 0xfffe then the param has no name, the former
4186 meaning that the next WORD is the type, the latter
4187 meaning that the next WORD is an offset to the type. */
4192 else if(*pArg
== 0xfffe) {
4196 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4201 if(HaveOffs
) { /* the next word is an offset to type */
4202 pType
= (WORD
*)(pBlk
+ *pArg
);
4203 SLTG_DoElem(pType
, pBlk
,
4204 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4209 pArg
= SLTG_DoElem(pArg
, pBlk
,
4210 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4213 /* Are we an optional param ? */
4214 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4215 pFuncDesc
->funcdesc
.cParamsOpt
)
4216 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4219 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4220 paramName
- pNameTable
, pTI
->pTypeLib
);
4222 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4226 pTI
->typeattr
.cFuncs
= cFuncs
;
4229 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4230 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4231 SLTG_TypeInfoTail
*pTITail
)
4234 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4236 if(pTIHeader
->href_table
!= 0xffffffff) {
4237 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4243 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4244 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4246 heap_free(ref_lookup
);
4250 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4251 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4252 const SLTG_TypeInfoTail
*pTITail
)
4255 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4257 if(pTIHeader
->href_table
!= 0xffffffff) {
4258 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4264 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4265 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4268 if (pTITail
->funcs_off
!= 0xffff)
4269 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4271 heap_free(ref_lookup
);
4273 if (TRACE_ON(typelib
))
4274 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4277 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4278 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4279 const SLTG_TypeInfoTail
*pTITail
)
4281 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4284 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4285 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4286 const SLTG_TypeInfoTail
*pTITail
)
4289 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4291 if (pTITail
->simple_alias
) {
4292 /* if simple alias, no more processing required */
4293 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4294 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4298 if(pTIHeader
->href_table
!= 0xffffffff) {
4299 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4303 /* otherwise it is an offset to a type */
4304 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4306 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4307 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4309 heap_free(ref_lookup
);
4312 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4313 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4314 const SLTG_TypeInfoTail
*pTITail
)
4316 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4317 if (pTIHeader
->href_table
!= 0xffffffff)
4318 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4321 if (pTITail
->vars_off
!= 0xffff)
4322 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4324 if (pTITail
->funcs_off
!= 0xffff)
4325 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4327 if (pTITail
->impls_off
!= 0xffff)
4328 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4330 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4331 * of dispinterface functions including the IDispatch ones, so
4332 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4333 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4335 heap_free(ref_lookup
);
4336 if (TRACE_ON(typelib
))
4337 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4340 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4341 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4342 const SLTG_TypeInfoTail
*pTITail
)
4344 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4347 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4348 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4349 const SLTG_TypeInfoTail
*pTITail
)
4351 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4352 if (pTIHeader
->href_table
!= 0xffffffff)
4353 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4356 if (pTITail
->vars_off
!= 0xffff)
4357 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4359 if (pTITail
->funcs_off
!= 0xffff)
4360 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4361 heap_free(ref_lookup
);
4362 if (TRACE_ON(typelib
))
4366 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4367 manageable copy of it into this */
4380 } SLTG_InternalOtherTypeInfo
;
4382 /****************************************************************************
4383 * ITypeLib2_Constructor_SLTG
4385 * loading a SLTG typelib from an in-memory image
4387 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4389 ITypeLibImpl
*pTypeLibImpl
;
4390 SLTG_Header
*pHeader
;
4391 SLTG_BlkEntry
*pBlkEntry
;
4395 LPVOID pBlk
, pFirstBlk
;
4396 SLTG_LibBlk
*pLibBlk
;
4397 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4398 char *pAfterOTIBlks
= NULL
;
4399 char *pNameTable
, *ptr
;
4402 ITypeInfoImpl
**ppTypeInfoImpl
;
4404 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4407 pTypeLibImpl
= TypeLibImpl_Constructor();
4408 if (!pTypeLibImpl
) return NULL
;
4412 TRACE_(typelib
)("header:\n");
4413 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4414 pHeader
->nrOfFileBlks
);
4415 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4416 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4417 pHeader
->SLTG_magic
);
4421 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4422 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4424 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4425 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4427 /* Next we have a magic block */
4428 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4430 /* Let's see if we're still in sync */
4431 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4432 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4433 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4436 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4437 sizeof(SLTG_DIR_MAGIC
))) {
4438 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4442 pIndex
= (SLTG_Index
*)(pMagic
+1);
4444 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4446 pFirstBlk
= pPad9
+ 1;
4448 /* We'll set up a ptr to the main library block, which is the last one. */
4450 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4451 pBlkEntry
[order
].next
!= 0;
4452 order
= pBlkEntry
[order
].next
- 1) {
4453 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4457 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4459 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4464 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4466 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4469 ptr
= (char*)pLibBlk
+ len
;
4471 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4475 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4477 w
= *(WORD
*)(ptr
+ 2);
4480 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4481 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4482 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4484 w
= *(WORD
*)(ptr
+ 4 + len
);
4486 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4488 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4489 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4490 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4492 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4493 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4494 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4496 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4497 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4500 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4501 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4502 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4503 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4504 len
+= sizeof(SLTG_OtherTypeInfo
);
4508 pAfterOTIBlks
= ptr
;
4510 /* Skip this WORD and get the next DWORD */
4511 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4513 /* Now add this to pLibBLk look at what we're pointing at and
4514 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4515 dust and we should be pointing at the beginning of the name
4518 pNameTable
= (char*)pLibBlk
+ len
;
4520 switch(*(WORD
*)pNameTable
) {
4527 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4531 pNameTable
+= 0x216;
4535 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4537 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4540 /* Hopefully we now have enough ptrs set up to actually read in
4541 some TypeInfos. It's not clear which order to do them in, so
4542 I'll just follow the links along the BlkEntry chain and read
4543 them in the order in which they are in the file */
4545 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4546 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4548 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4549 pBlkEntry
[order
].next
!= 0;
4550 order
= pBlkEntry
[order
].next
- 1, i
++) {
4552 SLTG_TypeInfoHeader
*pTIHeader
;
4553 SLTG_TypeInfoTail
*pTITail
;
4554 SLTG_MemberHeader
*pMemHeader
;
4556 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4557 FIXME_(typelib
)("Index strings don't match\n");
4558 heap_free(pOtherTypeInfoBlks
);
4563 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4564 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4565 heap_free(pOtherTypeInfoBlks
);
4568 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4569 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4570 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4572 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4573 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4574 (*ppTypeInfoImpl
)->index
= i
;
4575 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4576 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4577 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4578 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4579 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4580 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4581 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4582 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4584 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4585 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4587 if((pTIHeader
->typeflags1
& 7) != 2)
4588 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4589 if(pTIHeader
->typeflags3
!= 2)
4590 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4592 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4593 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4594 typekind_desc
[pTIHeader
->typekind
],
4595 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4596 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4598 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4600 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4602 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4603 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4604 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4606 switch(pTIHeader
->typekind
) {
4608 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4609 pTIHeader
, pTITail
);
4613 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4614 pTIHeader
, pTITail
);
4617 case TKIND_INTERFACE
:
4618 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4619 pTIHeader
, pTITail
);
4623 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4624 pTIHeader
, pTITail
);
4628 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4629 pTIHeader
, pTITail
);
4632 case TKIND_DISPATCH
:
4633 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4634 pTIHeader
, pTITail
);
4638 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4639 pTIHeader
, pTITail
);
4643 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4648 /* could get cFuncs, cVars and cImplTypes from here
4649 but we've already set those */
4650 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4666 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4669 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4670 FIXME("Somehow processed %d TypeInfos\n", i
);
4671 heap_free(pOtherTypeInfoBlks
);
4675 heap_free(pOtherTypeInfoBlks
);
4676 return &pTypeLibImpl
->ITypeLib2_iface
;
4679 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4681 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4683 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4685 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4686 IsEqualIID(riid
,&IID_ITypeLib
)||
4687 IsEqualIID(riid
,&IID_ITypeLib2
))
4689 *ppv
= &This
->ITypeLib2_iface
;
4691 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4692 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4694 *ppv
= &This
->ICreateTypeLib2_iface
;
4699 TRACE("-- Interface: E_NOINTERFACE\n");
4700 return E_NOINTERFACE
;
4703 IUnknown_AddRef((IUnknown
*)*ppv
);
4707 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4709 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4710 ULONG ref
= InterlockedIncrement(&This
->ref
);
4712 TRACE("(%p) ref=%u\n", This
, ref
);
4717 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4719 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4720 ULONG ref
= InterlockedDecrement(&This
->ref
);
4722 TRACE("(%p) ref=%u\n",This
, ref
);
4726 TLBImpLib
*pImpLib
, *pImpLibNext
;
4727 TLBRefType
*ref_type
, *ref_type_next
;
4728 TLBString
*tlbstr
, *tlbstr_next
;
4729 TLBGuid
*tlbguid
, *tlbguid_next
;
4732 /* remove cache entry */
4735 TRACE("removing from cache list\n");
4736 EnterCriticalSection(&cache_section
);
4737 if(This
->entry
.next
)
4738 list_remove(&This
->entry
);
4739 LeaveCriticalSection(&cache_section
);
4740 heap_free(This
->path
);
4742 TRACE(" destroying ITypeLib(%p)\n",This
);
4744 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4745 list_remove(&tlbstr
->entry
);
4746 SysFreeString(tlbstr
->str
);
4750 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4751 list_remove(&tlbstr
->entry
);
4752 SysFreeString(tlbstr
->str
);
4756 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4757 list_remove(&tlbguid
->entry
);
4761 TLB_FreeCustData(&This
->custdata_list
);
4763 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4764 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4765 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4767 heap_free(This
->pTypeDesc
);
4769 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4771 if (pImpLib
->pImpTypeLib
)
4772 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4773 SysFreeString(pImpLib
->name
);
4775 list_remove(&pImpLib
->entry
);
4779 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, ref_type_next
, &This
->ref_list
, TLBRefType
, entry
)
4781 list_remove(&ref_type
->entry
);
4782 heap_free(ref_type
);
4785 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4786 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4787 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4789 heap_free(This
->typeinfos
);
4797 /* ITypeLib::GetTypeInfoCount
4799 * Returns the number of type descriptions in the type library
4801 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4803 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4804 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4805 return This
->TypeInfoCount
;
4808 /* ITypeLib::GetTypeInfo
4810 * retrieves the specified type description in the library.
4812 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4815 ITypeInfo
**ppTInfo
)
4817 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4819 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4822 return E_INVALIDARG
;
4824 if(index
>= This
->TypeInfoCount
)
4825 return TYPE_E_ELEMENTNOTFOUND
;
4827 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4828 ITypeInfo_AddRef(*ppTInfo
);
4834 /* ITypeLibs::GetTypeInfoType
4836 * Retrieves the type of a type description.
4838 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4843 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4845 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4848 return E_INVALIDARG
;
4850 if(index
>= This
->TypeInfoCount
)
4851 return TYPE_E_ELEMENTNOTFOUND
;
4853 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4858 /* ITypeLib::GetTypeInfoOfGuid
4860 * Retrieves the type description that corresponds to the specified GUID.
4863 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4866 ITypeInfo
**ppTInfo
)
4868 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4871 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4873 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4874 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4875 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4876 ITypeInfo_AddRef(*ppTInfo
);
4881 return TYPE_E_ELEMENTNOTFOUND
;
4884 /* ITypeLib::GetLibAttr
4886 * Retrieves the structure that contains the library's attributes.
4889 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4893 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4895 TRACE("(%p, %p)\n", This
, attr
);
4897 if (!attr
) return E_INVALIDARG
;
4899 *attr
= heap_alloc(sizeof(**attr
));
4900 if (!*attr
) return E_OUTOFMEMORY
;
4902 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4903 (*attr
)->lcid
= This
->set_lcid
;
4904 (*attr
)->syskind
= This
->syskind
;
4905 (*attr
)->wMajorVerNum
= This
->ver_major
;
4906 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4907 (*attr
)->wLibFlags
= This
->libflags
;
4912 /* ITypeLib::GetTypeComp
4914 * Enables a client compiler to bind to a library's types, variables,
4915 * constants, and global functions.
4918 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4920 ITypeComp
**ppTComp
)
4922 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4924 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4925 *ppTComp
= &This
->ITypeComp_iface
;
4926 ITypeComp_AddRef(*ppTComp
);
4931 /* ITypeLib::GetDocumentation
4933 * Retrieves the library's documentation string, the complete Help file name
4934 * and path, and the context identifier for the library Help topic in the Help
4937 * On a successful return all non-null BSTR pointers will have been set,
4940 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4944 BSTR
*pBstrDocString
,
4945 DWORD
*pdwHelpContext
,
4946 BSTR
*pBstrHelpFile
)
4948 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4949 HRESULT result
= E_INVALIDARG
;
4952 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4954 pBstrName
, pBstrDocString
,
4955 pdwHelpContext
, pBstrHelpFile
);
4959 /* documentation for the typelib */
4964 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4972 if (This
->DocString
)
4974 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4978 *pBstrDocString
= NULL
;
4982 *pdwHelpContext
= This
->dwHelpContext
;
4988 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
4992 *pBstrHelpFile
= NULL
;
4999 /* for a typeinfo */
5000 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5002 if(SUCCEEDED(result
))
5004 result
= ITypeInfo_GetDocumentation(pTInfo
,
5008 pdwHelpContext
, pBstrHelpFile
);
5010 ITypeInfo_Release(pTInfo
);
5015 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5017 if (pBstrName
) SysFreeString (*pBstrName
);
5019 return STG_E_INSUFFICIENTMEMORY
;
5024 * Indicates whether a passed-in string contains the name of a type or member
5025 * described in the library.
5028 static HRESULT WINAPI
ITypeLib2_fnIsName(
5034 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5036 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5038 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5042 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5043 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5044 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5045 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5046 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5048 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5049 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5050 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5051 goto ITypeLib2_fnIsName_exit
;
5054 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5055 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5056 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5062 ITypeLib2_fnIsName_exit
:
5063 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5064 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5069 /* ITypeLib::FindName
5071 * Finds occurrences of a type description in a type library. This may be used
5072 * to quickly verify that a name exists in a type library.
5075 static HRESULT WINAPI
ITypeLib2_fnFindName(
5079 ITypeInfo
**ppTInfo
,
5083 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5088 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5090 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5091 return E_INVALIDARG
;
5093 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5094 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5095 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5099 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5100 memid
[count
] = MEMBERID_NIL
;
5101 goto ITypeLib2_fnFindName_exit
;
5104 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5105 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5107 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5108 memid
[count
] = func
->funcdesc
.memid
;
5109 goto ITypeLib2_fnFindName_exit
;
5113 var
= TLB_get_vardesc_by_name(pTInfo
, name
);
5115 memid
[count
] = var
->vardesc
.memid
;
5116 goto ITypeLib2_fnFindName_exit
;
5120 ITypeLib2_fnFindName_exit
:
5121 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5122 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5125 TRACE("found %d typeinfos\n", count
);
5132 /* ITypeLib::ReleaseTLibAttr
5134 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5137 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5139 TLIBATTR
*pTLibAttr
)
5141 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5142 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5143 heap_free(pTLibAttr
);
5146 /* ITypeLib2::GetCustData
5148 * gets the custom data
5150 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5155 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5156 TLBCustData
*pCData
;
5158 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5160 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5162 return TYPE_E_ELEMENTNOTFOUND
;
5164 VariantInit(pVarVal
);
5165 VariantCopy(pVarVal
, &pCData
->data
);
5170 /* ITypeLib2::GetLibStatistics
5172 * Returns statistics about a type library that are required for efficient
5173 * sizing of hash tables.
5176 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5178 ULONG
*pcUniqueNames
,
5179 ULONG
*pcchUniqueNames
)
5181 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5183 FIXME("(%p): stub!\n", This
);
5185 if(pcUniqueNames
) *pcUniqueNames
=1;
5186 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5190 /* ITypeLib2::GetDocumentation2
5192 * Retrieves the library's documentation string, the complete Help file name
5193 * and path, the localization context to use, and the context ID for the
5194 * library Help topic in the Help file.
5197 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5201 BSTR
*pbstrHelpString
,
5202 DWORD
*pdwHelpStringContext
,
5203 BSTR
*pbstrHelpStringDll
)
5205 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5209 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5211 /* the help string should be obtained from the helpstringdll,
5212 * using the _DLLGetDocumentation function, based on the supplied
5213 * lcid. Nice to do sometime...
5217 /* documentation for the typelib */
5219 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5220 if(pdwHelpStringContext
)
5221 *pdwHelpStringContext
=This
->dwHelpContext
;
5222 if(pbstrHelpStringDll
)
5223 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5229 /* for a typeinfo */
5230 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5232 if(SUCCEEDED(result
))
5234 ITypeInfo2
* pTInfo2
;
5235 result
= ITypeInfo_QueryInterface(pTInfo
,
5237 (LPVOID
*) &pTInfo2
);
5239 if(SUCCEEDED(result
))
5241 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5245 pdwHelpStringContext
,
5246 pbstrHelpStringDll
);
5248 ITypeInfo2_Release(pTInfo2
);
5251 ITypeInfo_Release(pTInfo
);
5257 static HRESULT
TLB_copy_all_custdata(const struct list
*custdata_list
, CUSTDATA
*pCustData
)
5259 TLBCustData
*pCData
;
5264 ct
= list_count(custdata_list
);
5266 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5267 if(!pCustData
->prgCustData
)
5268 return E_OUTOFMEMORY
;
5270 pCustData
->cCustData
= ct
;
5272 cdi
= pCustData
->prgCustData
;
5273 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5274 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5275 VariantInit(&cdi
->varValue
);
5276 hr
= VariantCopy(&cdi
->varValue
, &pCData
->data
);
5277 if(FAILED(hr
)) break;
5285 /* ITypeLib2::GetAllCustData
5287 * Gets all custom data items for the library.
5290 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5292 CUSTDATA
*pCustData
)
5294 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5295 TRACE("(%p)->(%p)\n", This
, pCustData
);
5296 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5299 static const ITypeLib2Vtbl tlbvt
= {
5300 ITypeLib2_fnQueryInterface
,
5302 ITypeLib2_fnRelease
,
5303 ITypeLib2_fnGetTypeInfoCount
,
5304 ITypeLib2_fnGetTypeInfo
,
5305 ITypeLib2_fnGetTypeInfoType
,
5306 ITypeLib2_fnGetTypeInfoOfGuid
,
5307 ITypeLib2_fnGetLibAttr
,
5308 ITypeLib2_fnGetTypeComp
,
5309 ITypeLib2_fnGetDocumentation
,
5311 ITypeLib2_fnFindName
,
5312 ITypeLib2_fnReleaseTLibAttr
,
5314 ITypeLib2_fnGetCustData
,
5315 ITypeLib2_fnGetLibStatistics
,
5316 ITypeLib2_fnGetDocumentation2
,
5317 ITypeLib2_fnGetAllCustData
5321 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5323 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5325 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5328 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5330 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5332 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5335 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5337 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5339 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5342 static HRESULT WINAPI
ITypeLibComp_fnBind(
5347 ITypeInfo
** ppTInfo
,
5348 DESCKIND
* pDescKind
,
5351 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5352 BOOL typemismatch
= FALSE
;
5355 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5357 *pDescKind
= DESCKIND_NONE
;
5358 pBindPtr
->lptcomp
= NULL
;
5361 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5362 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5363 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5365 /* FIXME: check wFlags here? */
5366 /* FIXME: we should use a hash table to look this info up using lHash
5367 * instead of an O(n) search */
5368 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5369 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5371 if (pTypeInfo
->Name
&& !wcscmp(pTypeInfo
->Name
->str
, szName
))
5373 *pDescKind
= DESCKIND_TYPECOMP
;
5374 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5375 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5376 TRACE("module or enum: %s\n", debugstr_w(szName
));
5381 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5382 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5384 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5387 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5388 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5390 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5393 else if (hr
== TYPE_E_TYPEMISMATCH
)
5394 typemismatch
= TRUE
;
5397 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5398 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5400 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5402 ITypeInfo
*subtypeinfo
;
5404 DESCKIND subdesckind
;
5406 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5407 &subtypeinfo
, &subdesckind
, &subbindptr
);
5408 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5410 TYPEDESC tdesc_appobject
;
5411 const VARDESC vardesc_appobject
=
5414 NULL
, /* lpstrSchema */
5429 VAR_STATIC
/* varkind */
5432 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5433 tdesc_appobject
.vt
= VT_USERDEFINED
;
5435 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5437 /* cleanup things filled in by Bind call so we can put our
5438 * application object data in there instead */
5439 switch (subdesckind
)
5441 case DESCKIND_FUNCDESC
:
5442 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5444 case DESCKIND_VARDESC
:
5445 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5450 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5452 if (pTypeInfo
->hreftype
== -1)
5453 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5455 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5459 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5460 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5461 ITypeInfo_AddRef(*ppTInfo
);
5464 else if (hr
== TYPE_E_TYPEMISMATCH
)
5465 typemismatch
= TRUE
;
5471 TRACE("type mismatch %s\n", debugstr_w(szName
));
5472 return TYPE_E_TYPEMISMATCH
;
5476 TRACE("name not found %s\n", debugstr_w(szName
));
5481 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5485 ITypeInfo
** ppTInfo
,
5486 ITypeComp
** ppTComp
)
5488 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5489 ITypeInfoImpl
*info
;
5491 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5493 if(!szName
|| !ppTInfo
|| !ppTComp
)
5494 return E_INVALIDARG
;
5496 info
= TLB_get_typeinfo_by_name(This
, szName
);
5503 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5504 ITypeInfo_AddRef(*ppTInfo
);
5505 *ppTComp
= &info
->ITypeComp_iface
;
5506 ITypeComp_AddRef(*ppTComp
);
5511 static const ITypeCompVtbl tlbtcvt
=
5514 ITypeLibComp_fnQueryInterface
,
5515 ITypeLibComp_fnAddRef
,
5516 ITypeLibComp_fnRelease
,
5518 ITypeLibComp_fnBind
,
5519 ITypeLibComp_fnBindType
5522 /*================== ITypeInfo(2) Methods ===================================*/
5523 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5525 ITypeInfoImpl
*pTypeInfoImpl
;
5527 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5530 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5531 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5532 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5533 pTypeInfoImpl
->ref
= 0;
5534 pTypeInfoImpl
->hreftype
= -1;
5535 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5536 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5537 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5538 list_init(pTypeInfoImpl
->pcustdata_list
);
5540 TRACE("(%p)\n", pTypeInfoImpl
);
5541 return pTypeInfoImpl
;
5544 /* ITypeInfo::QueryInterface
5546 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5551 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5553 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5556 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5557 IsEqualIID(riid
,&IID_ITypeInfo
)||
5558 IsEqualIID(riid
,&IID_ITypeInfo2
))
5559 *ppvObject
= &This
->ITypeInfo2_iface
;
5560 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5561 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5562 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5563 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5564 *ppvObject
= &This
->ITypeComp_iface
;
5567 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5568 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5571 TRACE("-- Interface: E_NOINTERFACE\n");
5572 return E_NOINTERFACE
;
5575 /* ITypeInfo::AddRef
5577 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5579 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5580 ULONG ref
= InterlockedIncrement(&This
->ref
);
5582 TRACE("(%p)->ref is %u\n",This
, ref
);
5584 if (ref
== 1 /* incremented from 0 */)
5585 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5590 static void typeinfo_release_funcdesc(TLBFuncDesc
*func
)
5594 for (i
= 0; i
< func
->funcdesc
.cParams
; ++i
)
5596 ELEMDESC
*elemdesc
= &func
->funcdesc
.lprgelemdescParam
[i
];
5597 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5598 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5599 TLB_FreeCustData(&func
->pParamDesc
[i
].custdata_list
);
5601 heap_free(func
->funcdesc
.lprgelemdescParam
);
5602 heap_free(func
->pParamDesc
);
5603 TLB_FreeCustData(&func
->custdata_list
);
5606 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5610 TRACE("destroying ITypeInfo(%p)\n",This
);
5612 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5614 typeinfo_release_funcdesc(&This
->funcdescs
[i
]);
5616 heap_free(This
->funcdescs
);
5618 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5620 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5621 if (pVInfo
->vardesc_create
) {
5622 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5623 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5624 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5625 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5627 TLB_FreeCustData(&pVInfo
->custdata_list
);
5629 heap_free(This
->vardescs
);
5631 if(This
->impltypes
){
5632 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5633 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5634 TLB_FreeCustData(&pImpl
->custdata_list
);
5636 heap_free(This
->impltypes
);
5639 TLB_FreeCustData(&This
->custdata_list
);
5644 /* ITypeInfo::Release
5646 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5648 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5649 ULONG ref
= InterlockedDecrement(&This
->ref
);
5651 TRACE("(%p)->(%u)\n",This
, ref
);
5655 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5656 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5657 if (not_attached_to_typelib
)
5659 /* otherwise This will be freed when typelib is freed */
5665 /* ITypeInfo::GetTypeAttr
5667 * Retrieves a TYPEATTR structure that contains the attributes of the type
5671 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5672 LPTYPEATTR
*ppTypeAttr
)
5674 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5677 TRACE("(%p)\n",This
);
5679 size
= sizeof(**ppTypeAttr
);
5680 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5681 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5683 *ppTypeAttr
= heap_alloc(size
);
5685 return E_OUTOFMEMORY
;
5687 **ppTypeAttr
= This
->typeattr
;
5688 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5690 if (This
->tdescAlias
)
5691 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5693 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5694 /* This should include all the inherited funcs */
5695 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5696 /* This is always the size of IDispatch's vtbl */
5697 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5698 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5703 /* ITypeInfo::GetTypeComp
5705 * Retrieves the ITypeComp interface for the type description, which enables a
5706 * client compiler to bind to the type description's members.
5709 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5710 ITypeComp
* *ppTComp
)
5712 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5714 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5716 *ppTComp
= &This
->ITypeComp_iface
;
5717 ITypeComp_AddRef(*ppTComp
);
5721 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5723 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5724 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5725 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5729 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5732 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5733 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5735 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5736 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5737 *buffer
+= sizeof(PARAMDESCEX
);
5738 *pparamdescex_dest
= *pparamdescex_src
;
5739 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5740 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5741 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5742 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5745 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5749 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5751 UINT len
= SysStringLen(str
), i
;
5752 for (i
= 0; i
< len
; ++i
)
5758 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5760 if (V_VT(var
) == VT_INT
)
5761 return VariantChangeType(var
, var
, 0, VT_I4
);
5762 else if (V_VT(var
) == VT_UINT
)
5763 return VariantChangeType(var
, var
, 0, VT_UI4
);
5764 else if (V_VT(var
) == VT_BSTR
)
5765 return TLB_SanitizeBSTR(V_BSTR(var
));
5770 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5772 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5773 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5776 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5780 SIZE_T size
= sizeof(*src
);
5784 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5785 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5786 for (i
= 0; i
< src
->cParams
; i
++)
5788 size
+= sizeof(ELEMDESC
);
5789 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5792 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5793 if (!dest
) return E_OUTOFMEMORY
;
5796 if (dispinterface
) /* overwrite funckind */
5797 dest
->funckind
= FUNC_DISPATCH
;
5798 buffer
= (char *)(dest
+ 1);
5800 dest
->oVft
= dest
->oVft
& 0xFFFC;
5802 if (dest
->cScodes
) {
5803 dest
->lprgscode
= (SCODE
*)buffer
;
5804 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5805 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5807 dest
->lprgscode
= NULL
;
5809 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5812 SysFreeString((BSTR
)dest
);
5816 if (dest
->cParams
) {
5817 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5818 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5819 for (i
= 0; i
< src
->cParams
; i
++)
5821 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5827 /* undo the above actions */
5828 for (i
= i
- 1; i
>= 0; i
--)
5829 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5830 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5831 SysFreeString((BSTR
)dest
);
5835 dest
->lprgelemdescParam
= NULL
;
5837 /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
5838 * This accounts for several arguments that are separate in the signature of
5839 * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
5840 if (dispinterface
&& (src
->funckind
!= FUNC_DISPATCH
))
5842 /* functions that have a [retval] parameter return this value into pVarResult.
5843 * [retval] is always the last parameter (if present) */
5844 if (dest
->cParams
&&
5845 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5847 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5848 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5850 ERR("elemdesc should have started with VT_PTR instead of:\n");
5852 dump_ELEMDESC(elemdesc
);
5853 return E_UNEXPECTED
;
5856 /* the type pointed to by this [retval] becomes elemdescFunc,
5857 * i.e. the function signature's return type.
5858 * We are using a flat buffer so there is no danger of leaking memory */
5859 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5861 /* remove the last parameter */
5864 else if (dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5865 /* Even if not otherwise replaced HRESULT is returned in pExcepInfo->scode,
5866 * not pVarResult. So the function signature should show no return value. */
5867 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5869 /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
5870 * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
5871 if (dest
->cParams
&& (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FLCID
))
5879 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5881 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5882 if (var_desc
->varkind
== VAR_CONST
)
5883 VariantClear(var_desc
->u
.lpvarValue
);
5884 SysFreeString((BSTR
)var_desc
);
5887 /* internal function to make the inherited interfaces' methods appear
5888 * part of the interface */
5889 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5890 UINT index
, const TLBFuncDesc
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5892 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5894 UINT implemented_funcs
= 0;
5899 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5903 ITypeInfo
*pSubTypeInfo
;
5906 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5910 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5913 &sub_funcs
, hrefoffset
);
5914 implemented_funcs
+= sub_funcs
;
5915 ITypeInfo_Release(pSubTypeInfo
);
5918 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5922 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5926 if (index
< implemented_funcs
)
5927 return E_INVALIDARG
;
5928 index
-= implemented_funcs
;
5930 if (index
>= This
->typeattr
.cFuncs
)
5931 return TYPE_E_ELEMENTNOTFOUND
;
5933 *ppFuncDesc
= &This
->funcdescs
[index
];
5937 static HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const TLBFuncDesc
**func_desc
, UINT
*hrefoffset
)
5939 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5941 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5942 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface
, index
, func_desc
, NULL
, hrefoffset
);
5944 if (index
>= This
->typeattr
.cFuncs
)
5945 return TYPE_E_ELEMENTNOTFOUND
;
5947 *func_desc
= &This
->funcdescs
[index
];
5951 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5953 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5956 switch (pTypeDesc
->vt
)
5958 case VT_USERDEFINED
:
5959 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5963 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5966 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5974 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5977 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5978 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5979 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5982 /* ITypeInfo::GetFuncDesc
5984 * Retrieves the FUNCDESC structure that contains information about a
5985 * specified function.
5988 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5989 LPFUNCDESC
*ppFuncDesc
)
5991 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5992 const TLBFuncDesc
*internal_funcdesc
;
5994 UINT hrefoffset
= 0;
5996 TRACE("(%p) index %d\n", This
, index
);
5999 return E_INVALIDARG
;
6001 if (This
->needs_layout
)
6002 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6004 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6005 &internal_funcdesc
, &hrefoffset
);
6008 WARN("description for function %d not found\n", index
);
6012 hr
= TLB_AllocAndInitFuncDesc(
6013 &internal_funcdesc
->funcdesc
,
6015 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6017 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
6018 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6020 TRACE("-- 0x%08x\n", hr
);
6024 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6028 SIZE_T size
= sizeof(*src
);
6031 if (src
->lpstrSchema
) size
+= (lstrlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6032 if (src
->varkind
== VAR_CONST
)
6033 size
+= sizeof(VARIANT
);
6034 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6036 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6037 if (!dest
) return E_OUTOFMEMORY
;
6040 buffer
= (char *)(dest
+ 1);
6041 if (src
->lpstrSchema
)
6044 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6045 len
= lstrlenW(src
->lpstrSchema
);
6046 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6047 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6050 if (src
->varkind
== VAR_CONST
)
6054 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6055 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6056 buffer
+= sizeof(VARIANT
);
6057 VariantInit(dest
->u
.lpvarValue
);
6058 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6061 SysFreeString((BSTR
)dest
);
6065 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6068 if (src
->varkind
== VAR_CONST
)
6069 VariantClear(dest
->u
.lpvarValue
);
6070 SysFreeString((BSTR
)dest
);
6077 /* ITypeInfo::GetVarDesc
6079 * Retrieves a VARDESC structure that describes the specified variable.
6082 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6083 LPVARDESC
*ppVarDesc
)
6085 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6086 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6088 TRACE("(%p) index %d\n", This
, index
);
6090 if(index
>= This
->typeattr
.cVars
)
6091 return TYPE_E_ELEMENTNOTFOUND
;
6093 if (This
->needs_layout
)
6094 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6096 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6099 /* internal function to make the inherited interfaces' methods appear
6100 * part of the interface, remembering if the top-level was dispinterface */
6101 static HRESULT
typeinfo_getnames( ITypeInfo
*iface
, MEMBERID memid
, BSTR
*names
,
6102 UINT max_names
, UINT
*num_names
, BOOL dispinterface
)
6104 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
6105 const TLBFuncDesc
*func_desc
;
6106 const TLBVarDesc
*var_desc
;
6111 func_desc
= TLB_get_funcdesc_by_memberid(This
, memid
);
6114 UINT params
= func_desc
->funcdesc
.cParams
;
6115 if (!max_names
|| !func_desc
->Name
)
6118 *names
= SysAllocString(TLB_get_bstr(func_desc
->Name
));
6121 if (dispinterface
&& (func_desc
->funcdesc
.funckind
!= FUNC_DISPATCH
))
6123 /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc */
6124 if ((params
> 0) && (func_desc
->funcdesc
.lprgelemdescParam
[params
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
6125 --params
; /* Invoke(pVarResult) supplies the [retval] parameter, so it's hidden from DISPPARAMS */
6126 if ((params
> 0) && (func_desc
->funcdesc
.lprgelemdescParam
[params
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FLCID
))
6127 --params
; /* Invoke(lcid) supplies the [lcid] parameter, so it's hidden from DISPPARAMS */
6130 for (i
= 0; i
< params
; i
++)
6132 if (*num_names
>= max_names
|| !func_desc
->pParamDesc
[i
].Name
)
6134 names
[*num_names
] = SysAllocString(TLB_get_bstr(func_desc
->pParamDesc
[i
].Name
));
6140 var_desc
= TLB_get_vardesc_by_memberid(This
, memid
);
6143 *names
= SysAllocString(TLB_get_bstr(var_desc
->Name
));
6148 if (This
->impltypes
&&
6149 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
))
6151 /* recursive search */
6154 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &parent
);
6155 if (SUCCEEDED(result
))
6157 result
= typeinfo_getnames(parent
, memid
, names
, max_names
, num_names
, dispinterface
);
6158 ITypeInfo_Release(parent
);
6161 WARN("Could not search inherited interface!\n");
6165 WARN("no names found\n");
6168 return TYPE_E_ELEMENTNOTFOUND
;
6173 /* ITypeInfo_GetNames
6175 * Retrieves the variable with the specified member ID (or the name of the
6176 * property or method and its parameters) that correspond to the specified
6179 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6180 BSTR
*names
, UINT max_names
, UINT
*num_names
)
6182 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6184 TRACE("(%p) memid 0x%08x max_names %d\n", This
, memid
, max_names
);
6186 if (!names
) return E_INVALIDARG
;
6188 return typeinfo_getnames((ITypeInfo
*)iface
, memid
, names
, max_names
, num_names
,
6189 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6192 /* ITypeInfo::GetRefTypeOfImplType
6194 * If a type description describes a COM class, it retrieves the type
6195 * description of the implemented interface types. For an interface,
6196 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6200 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6205 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6208 TRACE("(%p) index %d\n", This
, index
);
6209 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6213 /* only valid on dual interfaces;
6214 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6217 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6223 hr
= TYPE_E_ELEMENTNOTFOUND
;
6226 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6228 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6229 *pRefType
= This
->pTypeLib
->dispatch_href
;
6233 if(index
>= This
->typeattr
.cImplTypes
)
6234 hr
= TYPE_E_ELEMENTNOTFOUND
;
6236 *pRefType
= This
->impltypes
[index
].hRef
;
6237 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6245 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6247 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6253 /* ITypeInfo::GetImplTypeFlags
6255 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6256 * or base interface in a type description.
6258 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6259 UINT index
, INT
*pImplTypeFlags
)
6261 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6263 TRACE("(%p) index %d\n", This
, index
);
6266 return E_INVALIDARG
;
6268 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6269 *pImplTypeFlags
= 0;
6273 if(index
>= This
->typeattr
.cImplTypes
)
6274 return TYPE_E_ELEMENTNOTFOUND
;
6276 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6282 * Maps between member names and member IDs, and parameter names and
6285 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6286 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6288 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6289 const TLBVarDesc
*pVDesc
;
6293 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6296 /* init out parameters in case of failure */
6297 for (i
= 0; i
< cNames
; i
++)
6298 pMemId
[i
] = MEMBERID_NIL
;
6300 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6302 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6303 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6304 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6305 for(i
=1; i
< cNames
; i
++){
6306 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6307 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6309 if( j
<pFDesc
->funcdesc
.cParams
)
6312 ret
=DISP_E_UNKNOWNNAME
;
6314 TRACE("-- 0x%08x\n", ret
);
6318 pVDesc
= TLB_get_vardesc_by_name(This
, *rgszNames
);
6321 *pMemId
= pVDesc
->vardesc
.memid
;
6324 /* not found, see if it can be found in an inherited interface */
6325 if(This
->impltypes
) {
6326 /* recursive search */
6328 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6330 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6331 ITypeInfo_Release(pTInfo
);
6334 WARN("Could not search inherited interface!\n");
6336 WARN("no names found\n");
6337 return DISP_E_UNKNOWNNAME
;
6343 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6344 extern double call_double_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6345 __ASM_GLOBAL_FUNC( call_method
,
6347 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6348 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6349 "movl %esp,%ebp\n\t"
6350 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6352 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6354 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6355 "movl 12(%ebp),%edx\n\t"
6356 "movl %esp,%edi\n\t"
6359 "subl %edx,%edi\n\t"
6360 "andl $~15,%edi\n\t"
6361 "movl %edi,%esp\n\t"
6362 "movl 12(%ebp),%ecx\n\t"
6363 "movl 16(%ebp),%esi\n\t"
6366 "1:\tcall *8(%ebp)\n\t"
6367 "subl %esp,%edi\n\t"
6368 "movl 20(%ebp),%ecx\n\t"
6369 "movl %edi,(%ecx)\n\t"
6370 "leal -8(%ebp),%esp\n\t"
6372 __ASM_CFI(".cfi_same_value %edi\n\t")
6374 __ASM_CFI(".cfi_same_value %esi\n\t")
6376 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6377 __ASM_CFI(".cfi_same_value %ebp\n\t")
6379 __ASM_GLOBAL_FUNC( call_double_method
,
6380 "jmp " __ASM_NAME("call_method") )
6382 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6383 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6385 int argspos
= 0, stack_offset
;
6390 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6391 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6392 pvargResult
, V_VT(pvargResult
));
6394 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6396 FIXME("unsupported calling convention %d\n",cc
);
6397 return E_INVALIDARG
;
6400 /* maximum size for an argument is sizeof(VARIANT) */
6401 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6405 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6406 func
= vtable
[oVft
/sizeof(void *)];
6407 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6409 else func
= (void *)oVft
;
6415 args
[argspos
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6418 WARN("invalid return type %u\n", vtReturn
);
6420 return E_INVALIDARG
;
6425 for (i
= 0; i
< cActuals
; i
++)
6427 VARIANT
*arg
= prgpvarg
[i
];
6438 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6439 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6443 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6444 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6446 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6447 args
[argspos
++] = V_BOOL(arg
);
6450 args
[argspos
++] = V_UI4(arg
);
6453 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6461 call_method( func
, argspos
, args
, &stack_offset
);
6464 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6468 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6473 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6476 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6480 if (stack_offset
&& cc
== CC_STDCALL
)
6482 WARN( "stack pointer off by %d\n", stack_offset
);
6483 return DISP_E_BADCALLEE
;
6485 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6486 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6490 #elif defined(__x86_64__)
6492 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6493 extern double CDECL
call_double_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6494 __ASM_GLOBAL_FUNC( call_method
,
6496 __ASM_SEH(".seh_pushreg %rbp\n\t")
6497 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6498 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6499 "movq %rsp,%rbp\n\t"
6500 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6501 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6503 __ASM_SEH(".seh_pushreg %rsi\n\t")
6504 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6506 __ASM_SEH(".seh_pushreg %rdi\n\t")
6507 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6508 __ASM_SEH(".seh_endprologue\n\t")
6509 "movq %rcx,%rax\n\t"
6512 "cmovgq %rdx,%rcx\n\t"
6513 "leaq 0(,%rcx,8),%rdx\n\t"
6514 "subq %rdx,%rsp\n\t"
6515 "andq $~15,%rsp\n\t"
6516 "movq %rsp,%rdi\n\t"
6519 "movq 0(%rsp),%rcx\n\t"
6520 "movq 8(%rsp),%rdx\n\t"
6521 "movq 16(%rsp),%r8\n\t"
6522 "movq 24(%rsp),%r9\n\t"
6523 "movq 0(%rsp),%xmm0\n\t"
6524 "movq 8(%rsp),%xmm1\n\t"
6525 "movq 16(%rsp),%xmm2\n\t"
6526 "movq 24(%rsp),%xmm3\n\t"
6528 "leaq -16(%rbp),%rsp\n\t"
6530 __ASM_CFI(".cfi_same_value %rdi\n\t")
6532 __ASM_CFI(".cfi_same_value %rsi\n\t")
6533 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6535 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6536 __ASM_CFI(".cfi_same_value %rbp\n\t")
6538 __ASM_GLOBAL_FUNC( call_double_method
,
6539 "jmp " __ASM_NAME("call_method") )
6541 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6542 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6549 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6550 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6551 pvargResult
, V_VT(pvargResult
));
6553 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6555 FIXME("unsupported calling convention %d\n",cc
);
6556 return E_INVALIDARG
;
6559 /* maximum size for an argument is sizeof(DWORD_PTR) */
6560 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6564 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6565 func
= vtable
[oVft
/sizeof(void *)];
6566 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6568 else func
= (void *)oVft
;
6574 args
[argspos
++] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6577 WARN("invalid return type %u\n", vtReturn
);
6579 return E_INVALIDARG
;
6584 for (i
= 0; i
< cActuals
; i
++)
6586 VARIANT
*arg
= prgpvarg
[i
];
6592 args
[argspos
++] = (ULONG_PTR
)arg
;
6594 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6595 args
[argspos
++] = V_BOOL(arg
);
6598 args
[argspos
++] = V_UI8(arg
);
6601 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6607 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
);
6611 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
);
6615 call_method( func
, argspos
, args
);
6618 V_UI8(pvargResult
) = call_method( func
, argspos
, args
);
6622 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6623 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6627 #elif defined(__arm__)
6629 extern LONGLONG CDECL
call_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6630 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6631 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6632 __ASM_GLOBAL_FUNC( call_method
,
6635 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6636 * 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)
6639 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6640 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6642 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6643 "beq 1f\n\t" /* Skip allocation if no stack args */
6644 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6645 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6646 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6647 "subs r1, r1, #4\n\t" /* Decrement count */
6648 "bgt 2b\n\t" /* Loop till done */
6652 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6654 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6655 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6657 "blx ip\n\t" /* Call the target function */
6659 "mov sp, fp\n\t" /* Clean the stack using fp */
6660 "pop {fp, pc}\n\t" /* Restore fp and return */
6662 __ASM_GLOBAL_FUNC( call_float_method
,
6663 "b " __ASM_NAME("call_method") )
6664 __ASM_GLOBAL_FUNC( call_double_method
,
6665 "b " __ASM_NAME("call_method") )
6667 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6668 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6683 int rcount
; /* 32-bit register index count */
6685 int scount
= 0; /* single-precision float register index count */
6686 int dcount
= 0; /* double-precision float register index count */
6689 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6690 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6692 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6694 FIXME("unsupported calling convention %d\n",cc
);
6695 return E_INVALIDARG
;
6703 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6704 func
= vtable
[oVft
/sizeof(void *)];
6705 regs
.r
[rcount
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6707 else func
= (void *)oVft
;
6709 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6710 /* first as it will need to be in the 'r' registers: */
6715 regs
.r
[rcount
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6718 WARN("invalid return type %u\n", vtReturn
);
6719 return E_INVALIDARG
;
6720 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6724 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6725 args
= heap_alloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 4 );
6727 for (i
= 0; i
< cActuals
; i
++)
6729 VARIANT
*arg
= prgpvarg
[i
];
6730 DWORD
*pdwarg
= (DWORD
*)(arg
); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6731 int ntemp
; /* Used for counting words split between registers and stack */
6737 case VT_R8
: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6740 dcount
= max( (scount
+ 1) / 2, dcount
);
6743 regs
.sd
.d
[dcount
++] = V_R8(arg
);
6747 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6748 memcpy( &args
[argspos
], &V_R8(arg
), sizeof(V_R8(arg
)) );
6749 argspos
+= sizeof(V_R8(arg
)) / sizeof(DWORD
);
6753 case VT_I8
: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6758 rcount
+= (rcount
% 2); /* align rcount to 8-byte register pair */
6759 memcpy( ®s
.r
[rcount
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6760 rcount
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6764 rcount
= 4; /* Make sure we flag that all 'r' regs are full */
6765 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6766 memcpy( &args
[argspos
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6767 argspos
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6770 case VT_DECIMAL
: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6772 /* 8-byte align 'r' and/or stack: */
6774 rcount
+= (rcount
% 2);
6778 argspos
+= (argspos
% 2);
6780 ntemp
= sizeof(*arg
) / sizeof(DWORD
);
6784 regs
.r
[rcount
++] = *pdwarg
++;
6786 args
[argspos
++] = *pdwarg
++;
6790 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6792 regs
.r
[rcount
++] = V_BOOL(arg
);
6794 args
[argspos
++] = V_BOOL(arg
);
6796 case VT_R4
: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6798 if (!(scount
% 2)) scount
= max( scount
, dcount
* 2 );
6800 regs
.sd
.s
[scount
++] = V_R4(arg
);
6802 args
[argspos
++] = V_UI4(arg
);
6807 regs
.r
[rcount
++] = V_UI4(arg
);
6809 args
[argspos
++] = V_UI4(arg
);
6812 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6815 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 8-byte */
6819 case VT_EMPTY
: /* EMPTY = no return value */
6820 case VT_DECIMAL
: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6822 call_method( func
, argspos
, args
, (DWORD
*)®s
);
6825 V_R4(pvargResult
) = call_float_method( func
, argspos
, args
, (DWORD
*)®s
);
6829 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, (DWORD
*)®s
);
6834 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6837 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6841 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6842 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6846 #elif defined(__aarch64__)
6848 extern DWORD_PTR CDECL
call_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6849 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6850 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6851 __ASM_GLOBAL_FUNC( call_method
,
6852 "stp x29, x30, [sp, #-16]!\n\t"
6854 "sub sp, sp, x1, lsl #3\n\t"
6856 "1:\tsub x1, x1, #1\n\t"
6857 "ldr x4, [x2, x1, lsl #3]\n\t"
6858 "str x4, [sp, x1, lsl #3]\n\t"
6860 "2:\tmov x16, x0\n\t"
6862 "ldp d0, d1, [x9]\n\t"
6863 "ldp d2, d3, [x9, #0x10]\n\t"
6864 "ldp d4, d5, [x9, #0x20]\n\t"
6865 "ldp d6, d7, [x9, #0x30]\n\t"
6866 "ldp x0, x1, [x9, #0x40]\n\t"
6867 "ldp x2, x3, [x9, #0x50]\n\t"
6868 "ldp x4, x5, [x9, #0x60]\n\t"
6869 "ldp x6, x7, [x9, #0x70]\n\t"
6870 "ldr x8, [x9, #0x80]\n\t"
6873 "ldp x29, x30, [sp], #16\n\t"
6875 __ASM_GLOBAL_FUNC( call_float_method
,
6876 "b " __ASM_NAME("call_method") )
6877 __ASM_GLOBAL_FUNC( call_double_method
,
6878 "b " __ASM_NAME("call_method") )
6880 HRESULT WINAPI
DispCallFunc( void *instance
, ULONG_PTR offset
, CALLCONV cc
, VARTYPE ret_type
, UINT count
,
6881 VARTYPE
*types
, VARIANTARG
**vargs
, VARIANT
*result
)
6896 int rcount
; /* 64-bit register index count */
6897 int fpcount
= 0; /* float register index count */
6899 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6900 instance
, offset
, cc
, ret_type
, count
, types
, vargs
, result
, V_VT(result
));
6902 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6904 FIXME("unsupported calling convention %d\n",cc
);
6905 return E_INVALIDARG
;
6913 const FARPROC
*vtable
= *(FARPROC
**)instance
;
6914 func
= vtable
[offset
/sizeof(void *)];
6915 regs
.x
[rcount
++] = (DWORD_PTR
)instance
; /* the This pointer is always the first parameter */
6917 else func
= (void *)offset
;
6919 /* maximum size for an argument is 16 */
6920 args
= heap_alloc( 16 * count
);
6922 for (i
= 0; i
< count
; i
++)
6924 VARIANT
*arg
= vargs
[i
];
6929 if (fpcount
< 8) regs
.fp
[fpcount
++].f
= V_R4(arg
);
6930 else *(float *)&args
[argspos
++] = V_R4(arg
);
6934 if (fpcount
< 8) regs
.fp
[fpcount
++].d
= V_R8(arg
);
6935 else *(double *)&args
[argspos
++] = V_R8(arg
);
6940 memcpy( ®s
.x
[rcount
], arg
, sizeof(*arg
) );
6945 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6950 if (rcount
< 8) regs
.x
[rcount
++] = (DWORD_PTR
)arg
;
6951 else args
[argspos
++] = (DWORD_PTR
)arg
;
6953 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6954 if (rcount
< 8) regs
.x
[rcount
++] = V_BOOL(arg
);
6955 else args
[argspos
++] = V_BOOL(arg
);
6958 if (rcount
< 8) regs
.x
[rcount
++] = V_UI8(arg
);
6959 else args
[argspos
++] = V_UI8(arg
);
6962 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(types
[i
]), debugstr_variant(arg
));
6965 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 16-byte */
6971 return E_INVALIDARG
;
6974 regs
.x
[8] = (DWORD_PTR
)result
; /* x8 is a pointer to the result */
6975 call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6978 V_R4(result
) = call_float_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6982 V_R8(result
) = call_double_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6985 V_UI8(result
) = call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6989 if (ret_type
!= VT_VARIANT
) V_VT(result
) = ret_type
;
6990 TRACE("retval: %s\n", debugstr_variant(result
));
6994 #else /* __aarch64__ */
6996 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6997 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6999 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7000 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
7006 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
7009 ITypeInfo
*tinfo2
= NULL
;
7010 TYPEATTR
*tattr
= NULL
;
7012 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
7015 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
7017 tdesc
->u
.hreftype
, hr
);
7020 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
7023 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
7024 ITypeInfo_Release(tinfo2
);
7028 switch (tattr
->typekind
)
7035 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
7038 case TKIND_INTERFACE
:
7039 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
7045 case TKIND_DISPATCH
:
7054 FIXME("TKIND_RECORD unhandled.\n");
7059 FIXME("TKIND_UNION unhandled.\n");
7064 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
7068 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7069 ITypeInfo_Release(tinfo2
);
7073 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
7077 /* enforce only one level of pointer indirection */
7078 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
7080 tdesc
= tdesc
->u
.lptdesc
;
7082 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7083 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7084 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7085 if ((tdesc
->vt
== VT_USERDEFINED
) ||
7086 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
7088 VARTYPE vt_userdefined
= 0;
7089 const TYPEDESC
*tdesc_userdefined
= tdesc
;
7090 if (tdesc
->vt
== VT_PTR
)
7092 vt_userdefined
= VT_BYREF
;
7093 tdesc_userdefined
= tdesc
->u
.lptdesc
;
7095 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
7097 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
7098 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
7100 *vt
|= vt_userdefined
;
7112 case VT_USERDEFINED
:
7113 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
7120 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
7121 hr
= DISP_E_BADVARTYPE
;
7125 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
7140 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, HREFTYPE href
, GUID
*guid
)
7147 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
7151 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
7153 ITypeInfo_Release(tinfo2
);
7157 switch(tattr
->typekind
) {
7159 hres
= get_iface_guid(tinfo2
, tattr
->tdescAlias
.u
.hreftype
, guid
);
7162 case TKIND_INTERFACE
:
7163 case TKIND_DISPATCH
:
7164 *guid
= tattr
->guid
;
7168 for (i
= 0; i
< tattr
->cImplTypes
; i
++)
7170 ITypeInfo_GetImplTypeFlags(tinfo2
, i
, &flags
);
7171 if (flags
& IMPLTYPEFLAG_FDEFAULT
)
7175 if (i
== tattr
->cImplTypes
)
7178 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo2
, i
, &href
);
7179 if (SUCCEEDED(hres
))
7180 hres
= get_iface_guid(tinfo2
, href
, guid
);
7184 ERR("Unexpected typekind %d\n", tattr
->typekind
);
7185 hres
= E_UNEXPECTED
;
7188 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7189 ITypeInfo_Release(tinfo2
);
7193 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
7195 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
7198 #define INVBUF_ELEMENT_SIZE \
7199 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7200 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7201 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7202 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7203 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7204 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7205 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7206 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7208 static HRESULT WINAPI
ITypeInfo_fnInvoke(
7213 DISPPARAMS
*pDispParams
,
7214 VARIANT
*pVarResult
,
7215 EXCEPINFO
*pExcepInfo
,
7218 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7220 unsigned int var_index
;
7223 const TLBFuncDesc
*pFuncInfo
;
7226 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7227 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
7230 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7231 return DISP_E_MEMBERNOTFOUND
;
7235 ERR("NULL pDispParams not allowed\n");
7236 return E_INVALIDARG
;
7239 dump_DispParms(pDispParams
);
7241 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7243 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7244 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7245 return E_INVALIDARG
;
7248 /* we do this instead of using GetFuncDesc since it will return a fake
7249 * FUNCDESC for dispinterfaces and we want the real function description */
7250 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7251 pFuncInfo
= &This
->funcdescs
[fdc
];
7252 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7253 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7254 !func_restricted( &pFuncInfo
->funcdesc
))
7258 if (fdc
< This
->typeattr
.cFuncs
) {
7259 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7263 TRACE("invoking:\n");
7264 dump_TLBFuncDescOne(pFuncInfo
);
7267 switch (func_desc
->funckind
) {
7268 case FUNC_PUREVIRTUAL
:
7269 case FUNC_VIRTUAL
: {
7270 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7272 VARIANT retval
; /* pointer for storing byref retvals in */
7273 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7274 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7275 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7276 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7277 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7278 UINT vargs_converted
=0;
7283 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7285 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7287 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7288 hres
= DISP_E_PARAMNOTFOUND
;
7293 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7295 ERR("functions with the vararg attribute do not support named arguments\n");
7296 hres
= DISP_E_NONAMEDARGS
;
7300 for (i
= 0; i
< func_desc
->cParams
; i
++)
7302 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7303 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7308 TRACE("changing args\n");
7309 for (i
= 0; i
< func_desc
->cParams
; i
++)
7311 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7312 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7313 VARIANTARG
*src_arg
;
7315 if (wParamFlags
& PARAMFLAG_FLCID
)
7318 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7320 V_I4(arg
) = This
->pTypeLib
->lcid
;
7329 for (j
= 0; j
< cNamedArgs
; j
++)
7330 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7332 src_arg
= &pDispParams
->rgvarg
[j
];
7337 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7339 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7343 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7345 /* under most conditions the caller is not allowed to
7346 * pass in a dispparam arg in the index of what would be
7347 * the retval parameter. however, there is an exception
7348 * where the extra parameter is used in an extra
7349 * IDispatch::Invoke below */
7350 if ((i
< pDispParams
->cArgs
) &&
7351 ((func_desc
->cParams
!= 1) || !pVarResult
||
7352 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7354 hres
= DISP_E_BADPARAMCOUNT
;
7358 /* note: this check is placed so that if the caller passes
7359 * in a VARIANTARG for the retval we just ignore it, like
7361 if (i
== func_desc
->cParams
- 1)
7364 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7365 memset(arg
, 0, sizeof(*arg
));
7366 V_VT(arg
) = rgvt
[i
];
7367 memset(&retval
, 0, sizeof(retval
));
7368 V_BYREF(arg
) = &retval
;
7372 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7373 hres
= E_UNEXPECTED
;
7377 else if (src_arg
&& !((wParamFlags
& PARAMFLAG_FOPT
) &&
7378 V_VT(src_arg
) == VT_ERROR
&& V_ERROR(src_arg
) == DISP_E_PARAMNOTFOUND
))
7380 TRACE("%s\n", debugstr_variant(src_arg
));
7382 if(rgvt
[i
]!=V_VT(src_arg
))
7384 if (rgvt
[i
] == VT_VARIANT
)
7385 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7386 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7388 if (rgvt
[i
] == V_VT(src_arg
))
7389 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7392 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7393 if (wParamFlags
& PARAMFLAG_FIN
)
7394 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7395 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7397 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7399 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7401 SAFEARRAYBOUND bound
;
7405 bound
.cElements
= pDispParams
->cArgs
-i
;
7406 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7408 ERR("SafeArrayCreate failed\n");
7411 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7414 ERR("SafeArrayAccessData failed with %x\n", hres
);
7415 SafeArrayDestroy(a
);
7418 for (j
= 0; j
< bound
.cElements
; j
++)
7419 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7420 hres
= SafeArrayUnaccessData(a
);
7423 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7424 SafeArrayDestroy(a
);
7427 if (rgvt
[i
] & VT_BYREF
)
7428 V_BYREF(&rgvarg
[i
]) = &a
;
7430 V_ARRAY(&rgvarg
[i
]) = a
;
7431 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7433 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7435 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7436 if (wParamFlags
& PARAMFLAG_FIN
)
7437 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7439 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7440 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7441 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7443 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7445 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7446 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7450 /* FIXME: this doesn't work for VT_BYREF arguments if
7451 * they are not the same type as in the paramdesc */
7452 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7453 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7454 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7459 ERR("failed to convert param %d to %s from %s\n", i
,
7460 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7463 prgpvarg
[i
] = &rgvarg
[i
];
7467 prgpvarg
[i
] = src_arg
;
7470 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7471 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7472 && V_UNKNOWN(prgpvarg
[i
])) {
7473 IUnknown
*userdefined_iface
;
7476 if (tdesc
->vt
== VT_PTR
)
7477 tdesc
= tdesc
->u
.lptdesc
;
7479 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->u
.hreftype
, &guid
);
7483 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7485 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7489 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7490 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7493 else if (wParamFlags
& PARAMFLAG_FOPT
)
7496 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7497 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7499 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7505 VARIANTARG
*missing_arg
;
7506 /* if the function wants a pointer to a variant then
7507 * set that up, otherwise just pass the VT_ERROR in
7508 * the argument by value */
7509 if (rgvt
[i
] & VT_BYREF
)
7511 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7512 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7513 V_VARIANTREF(arg
) = missing_arg
;
7517 V_VT(missing_arg
) = VT_ERROR
;
7518 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7523 hres
= DISP_E_BADPARAMCOUNT
;
7527 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7529 /* VT_VOID is a special case for return types, so it is not
7530 * handled in the general function */
7531 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7532 V_VT(&varresult
) = VT_EMPTY
;
7535 V_VT(&varresult
) = 0;
7536 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7537 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7540 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7541 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7542 prgpvarg
, &varresult
);
7544 vargs_converted
= 0;
7546 for (i
= 0; i
< func_desc
->cParams
; i
++)
7548 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7549 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7551 if (wParamFlags
& PARAMFLAG_FLCID
)
7553 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7555 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7559 VariantInit(pVarResult
);
7560 /* deref return value */
7561 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7564 VARIANT_ClearInd(prgpvarg
[i
]);
7566 else if (vargs_converted
< pDispParams
->cArgs
)
7568 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7569 if (wParamFlags
& PARAMFLAG_FOUT
)
7571 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7573 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7577 ERR("failed to convert param %d to vt %d\n", i
,
7578 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7583 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7584 func_desc
->cParamsOpt
< 0 &&
7585 i
== func_desc
->cParams
-1)
7587 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7590 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7593 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7596 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7599 ERR("SafeArrayAccessData failed with %x\n", hres
);
7602 for (j
= 0; j
<= ubound
; j
++)
7603 VariantClear(&v
[j
]);
7604 hres
= SafeArrayUnaccessData(a
);
7607 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7611 VariantClear(&rgvarg
[i
]);
7614 else if (wParamFlags
& PARAMFLAG_FOPT
)
7616 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7617 VariantClear(&rgvarg
[i
]);
7620 VariantClear(&missing_arg
[i
]);
7623 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7625 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7626 hres
= DISP_E_EXCEPTION
;
7629 IErrorInfo
*pErrorInfo
;
7630 pExcepInfo
->scode
= V_ERROR(&varresult
);
7631 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7633 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7634 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7635 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7636 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7638 IErrorInfo_Release(pErrorInfo
);
7642 if (V_VT(&varresult
) != VT_ERROR
)
7644 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7648 VariantClear(pVarResult
);
7649 *pVarResult
= varresult
;
7652 VariantClear(&varresult
);
7655 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7656 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7657 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7658 (pDispParams
->cArgs
!= 0))
7660 if (V_VT(pVarResult
) == VT_DISPATCH
)
7662 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7663 /* Note: not VariantClear; we still need the dispatch
7664 * pointer to be valid */
7665 VariantInit(pVarResult
);
7666 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7667 GetSystemDefaultLCID(), wFlags
,
7668 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7669 IDispatch_Release(pDispatch
);
7673 VariantClear(pVarResult
);
7674 hres
= DISP_E_NOTACOLLECTION
;
7682 case FUNC_DISPATCH
: {
7685 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7686 if (SUCCEEDED(hres
)) {
7687 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7688 hres
= IDispatch_Invoke(
7689 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7690 pVarResult
,pExcepInfo
,pArgErr
7693 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7694 IDispatch_Release(disp
);
7696 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7700 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7705 TRACE("-- 0x%08x\n", hres
);
7708 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7711 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7712 if(FAILED(hres
)) return hres
;
7714 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7715 dump_VARDESC(var_desc
);
7716 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7720 /* not found, look for it in inherited interfaces */
7721 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7722 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7723 if(This
->impltypes
) {
7724 /* recursive search */
7726 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7727 if(SUCCEEDED(hres
)){
7728 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7729 ITypeInfo_Release(pTInfo
);
7732 WARN("Could not search inherited interface!\n");
7735 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7736 return DISP_E_MEMBERNOTFOUND
;
7739 /* ITypeInfo::GetDocumentation
7741 * Retrieves the documentation string, the complete Help file name and path,
7742 * and the context ID for the Help topic for a specified type description.
7744 * (Can be tested by the Visual Basic Editor in Word for instance.)
7746 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7747 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7748 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7750 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7751 const TLBFuncDesc
*pFDesc
;
7752 const TLBVarDesc
*pVDesc
;
7753 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7754 " HelpContext(%p) HelpFile(%p)\n",
7755 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7756 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7758 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7760 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7762 *pdwHelpContext
=This
->dwHelpContext
;
7764 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7766 }else {/* for a member */
7767 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
7770 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7772 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7774 *pdwHelpContext
=pFDesc
->helpcontext
;
7776 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7779 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
7782 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7784 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7786 *pdwHelpContext
=pVDesc
->HelpContext
;
7788 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7793 if(This
->impltypes
&&
7794 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7795 /* recursive search */
7798 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7799 if(SUCCEEDED(result
)) {
7800 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7801 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7802 ITypeInfo_Release(pTInfo
);
7805 WARN("Could not search inherited interface!\n");
7808 WARN("member %d not found\n", memid
);
7809 return TYPE_E_ELEMENTNOTFOUND
;
7812 /* ITypeInfo::GetDllEntry
7814 * Retrieves a description or specification of an entry point for a function
7817 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7818 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7821 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7822 const TLBFuncDesc
*pFDesc
;
7824 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7826 if (pBstrDllName
) *pBstrDllName
= NULL
;
7827 if (pBstrName
) *pBstrName
= NULL
;
7828 if (pwOrdinal
) *pwOrdinal
= 0;
7830 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7831 return TYPE_E_BADMODULEKIND
;
7833 pFDesc
= TLB_get_funcdesc_by_memberid_invkind(This
, memid
, invKind
);
7834 if (!pFDesc
) return TYPE_E_ELEMENTNOTFOUND
;
7836 dump_TypeInfo(This
);
7837 if (TRACE_ON(ole
)) dump_TLBFuncDescOne(pFDesc
);
7839 if (pBstrDllName
) *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7841 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1))
7843 if (pBstrName
) *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7844 if (pwOrdinal
) *pwOrdinal
= -1;
7848 if (pBstrName
) *pBstrName
= NULL
;
7849 if (pwOrdinal
) *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7854 /* internal function to make the inherited interfaces' methods appear
7855 * part of the interface */
7856 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7857 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7859 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7862 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7864 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7866 ITypeInfo
*pSubTypeInfo
;
7868 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7872 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7874 ITypeInfo_Release(pSubTypeInfo
);
7878 *hRefType
-= DISPATCH_HREF_OFFSET
;
7880 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7881 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7886 struct search_res_tlb_params
7892 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7894 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7895 WCHAR szPath
[MAX_PATH
+1];
7896 ITypeLib
*pTLib
= NULL
;
7900 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7903 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7906 if (swprintf(szPath
+ len
, ARRAY_SIZE(szPath
) - len
, L
"\\%d", LOWORD(lpszName
)) < 0)
7909 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7912 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7913 if (IsEqualGUID(params
->guid
, impl
->guid
))
7915 params
->pTLib
= pTLib
;
7916 return FALSE
; /* stop enumeration */
7918 ITypeLib_Release(pTLib
);
7924 /* ITypeInfo::GetRefTypeInfo
7926 * If a type description references other type descriptions, it retrieves
7927 * the referenced type descriptions.
7929 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7932 ITypeInfo
**ppTInfo
)
7934 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7935 ITypeInfo
*type_info
= NULL
;
7936 HRESULT result
= E_FAIL
;
7937 TLBRefType
*ref_type
;
7941 return E_INVALIDARG
;
7943 if ((INT
)hRefType
< 0) {
7944 ITypeInfoImpl
*pTypeInfoImpl
;
7946 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7947 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7948 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7949 return TYPE_E_ELEMENTNOTFOUND
;
7951 /* when we meet a DUAL typeinfo, we must create the alternate
7954 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7956 *pTypeInfoImpl
= *This
;
7957 pTypeInfoImpl
->ref
= 0;
7958 list_init(&pTypeInfoImpl
->custdata_list
);
7960 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7961 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7963 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7965 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7966 /* the AddRef implicitly adds a reference to the parent typelib, which
7967 * stops the copied data from being destroyed until the new typeinfo's
7968 * refcount goes to zero, but we need to signal to the new instance to
7969 * not free its data structures when it is destroyed */
7970 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7971 ITypeInfo_AddRef(*ppTInfo
);
7973 TRACE("got dual interface %p\n", *ppTInfo
);
7977 if ((hRefType
& DISPATCH_HREF_MASK
) && (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7978 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &hRefType
, ppTInfo
);
7980 if(!(hRefType
& 0x1))
7982 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7984 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7987 type_info
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7988 ITypeInfo_AddRef(type_info
);
7996 ITypeLib
*pTLib
= NULL
;
7998 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
8000 if(ref_type
->reference
== (hRefType
& (~0x3)))
8003 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
8005 FIXME("Can't find pRefType for ref %x\n", hRefType
);
8009 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
8011 TRACE("internal reference\n");
8012 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
8014 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
8015 TRACE("typeinfo in imported typelib that is already loaded\n");
8016 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
8017 ITypeLib_AddRef(pTLib
);
8020 /* Search in cached typelibs */
8021 ITypeLibImpl
*entry
;
8023 EnterCriticalSection(&cache_section
);
8024 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
8027 && IsEqualIID(&entry
->guid
->guid
, TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
))
8028 && entry
->ver_major
== ref_type
->pImpTLInfo
->wVersionMajor
8029 && entry
->ver_minor
== ref_type
->pImpTLInfo
->wVersionMinor
8030 && entry
->set_lcid
== ref_type
->pImpTLInfo
->lcid
)
8032 TRACE("got cached %p\n", entry
);
8033 pTLib
= (ITypeLib
*)&entry
->ITypeLib2_iface
;
8034 ITypeLib_AddRef(pTLib
);
8039 LeaveCriticalSection(&cache_section
);
8043 struct search_res_tlb_params params
;
8045 TRACE("typeinfo in imported typelib that isn't already loaded\n");
8047 /* Search in resource table */
8048 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
8049 params
.pTLib
= NULL
;
8050 EnumResourceNamesW(NULL
, L
"TYPELIB", search_res_tlb
, (LONG_PTR
)¶ms
);
8053 pTLib
= params
.pTLib
;
8062 /* Search on disk */
8063 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
8064 ref_type
->pImpTLInfo
->wVersionMajor
,
8065 ref_type
->pImpTLInfo
->wVersionMinor
,
8066 This
->pTypeLib
->syskind
,
8067 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
8069 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
8071 result
= LoadTypeLib(libnam
, &pTLib
);
8072 SysFreeString(libnam
);
8075 if(SUCCEEDED(result
)) {
8076 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
8077 ITypeLib_AddRef(pTLib
);
8081 if(SUCCEEDED(result
)) {
8082 if(ref_type
->index
== TLB_REF_USE_GUID
)
8083 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), &type_info
);
8085 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, &type_info
);
8088 ITypeLib_Release(pTLib
);
8091 WARN("(%p) failed hreftype 0x%04x\n", This
, hRefType
);
8096 if ((hRefType
& 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info
, -2, ppTInfo
)))
8097 ITypeInfo_Release(type_info
);
8098 else *ppTInfo
= type_info
;
8100 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
8101 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
8105 /* ITypeInfo::AddressOfMember
8107 * Retrieves the addresses of static functions or variables, such as those
8110 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
8111 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
8113 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8119 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
8121 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
8125 module
= LoadLibraryW(dll
);
8128 ERR("couldn't load %s\n", debugstr_w(dll
));
8130 SysFreeString(entry
);
8131 return STG_E_FILENOTFOUND
;
8133 /* FIXME: store library somewhere where we can free it */
8138 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
8139 entryA
= heap_alloc(len
);
8140 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
8142 *ppv
= GetProcAddress(module
, entryA
);
8144 ERR("function not found %s\n", debugstr_a(entryA
));
8150 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
8152 ERR("function not found %d\n", ordinal
);
8156 SysFreeString(entry
);
8159 return TYPE_E_DLLFUNCTIONNOTFOUND
;
8164 /* ITypeInfo::CreateInstance
8166 * Creates a new instance of a type that describes a component object class
8169 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
8170 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
8172 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8176 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
8182 WARN("Not able to aggregate\n");
8183 return CLASS_E_NOAGGREGATION
;
8186 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
8187 if(FAILED(hr
)) return hr
;
8189 if(pTA
->typekind
!= TKIND_COCLASS
)
8191 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
8197 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
8200 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
8201 TRACE("GetActiveObject rets %08x\n", hr
);
8204 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
8205 IUnknown_Release(pUnk
);
8210 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
8211 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8215 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8219 /* ITypeInfo::GetMops
8221 * Retrieves marshalling information.
8223 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
8226 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8227 FIXME("(%p %d) stub!\n", This
, memid
);
8232 /* ITypeInfo::GetContainingTypeLib
8234 * Retrieves the containing type library and the index of the type description
8235 * within that type library.
8237 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8238 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8240 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8242 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8244 *pIndex
=This
->index
;
8245 TRACE("returning pIndex=%d\n", *pIndex
);
8249 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8250 ITypeLib_AddRef(*ppTLib
);
8251 TRACE("returning ppTLib=%p\n", *ppTLib
);
8257 /* ITypeInfo::ReleaseTypeAttr
8259 * Releases a TYPEATTR previously returned by Get
8262 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8263 TYPEATTR
* pTypeAttr
)
8265 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8266 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8267 heap_free(pTypeAttr
);
8270 /* ITypeInfo::ReleaseFuncDesc
8272 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8274 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8276 FUNCDESC
*pFuncDesc
)
8278 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8281 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8283 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8284 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8285 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8287 SysFreeString((BSTR
)pFuncDesc
);
8290 /* ITypeInfo::ReleaseVarDesc
8292 * Releases a VARDESC previously returned by GetVarDesc.
8294 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8297 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8298 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8300 TLB_FreeVarDesc(pVarDesc
);
8303 /* ITypeInfo2::GetTypeKind
8305 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8308 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8309 TYPEKIND
*pTypeKind
)
8311 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8312 *pTypeKind
= This
->typeattr
.typekind
;
8313 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8317 /* ITypeInfo2::GetTypeFlags
8319 * Returns the type flags without any allocations. This returns a DWORD type
8320 * flag, which expands the type flags without growing the TYPEATTR (type
8324 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8326 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8327 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8328 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
8332 /* ITypeInfo2::GetFuncIndexOfMemId
8333 * Binds to a specific member based on a known DISPID, where the member name
8334 * is not known (for example, when binding to a default member).
8337 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8338 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8340 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8344 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8345 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8346 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8349 if(fdc
< This
->typeattr
.cFuncs
) {
8353 result
= TYPE_E_ELEMENTNOTFOUND
;
8355 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
8356 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8360 /* TypeInfo2::GetVarIndexOfMemId
8362 * Binds to a specific member based on a known DISPID, where the member name
8363 * is not known (for example, when binding to a default member).
8366 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8367 MEMBERID memid
, UINT
*pVarIndex
)
8369 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8370 TLBVarDesc
*pVarInfo
;
8372 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8374 pVarInfo
= TLB_get_vardesc_by_memberid(This
, memid
);
8376 return TYPE_E_ELEMENTNOTFOUND
;
8378 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8383 /* ITypeInfo2::GetCustData
8385 * Gets the custom data
8387 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8392 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8393 TLBCustData
*pCData
;
8395 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8397 if(!guid
|| !pVarVal
)
8398 return E_INVALIDARG
;
8400 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8402 VariantInit( pVarVal
);
8404 VariantCopy( pVarVal
, &pCData
->data
);
8406 VariantClear( pVarVal
);
8410 /* ITypeInfo2::GetFuncCustData
8412 * Gets the custom data
8414 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8420 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8421 const TLBFuncDesc
*desc
;
8426 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8428 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &desc
, &hrefoffset
);
8431 WARN("description for function %d not found\n", index
);
8435 VariantInit(pVarVal
);
8436 data
= TLB_get_custdata_by_guid(&desc
->custdata_list
, guid
);
8437 return data
? VariantCopy(pVarVal
, &data
->data
) : S_OK
;
8440 /* ITypeInfo2::GetParamCustData
8442 * Gets the custom data
8444 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8451 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8452 const TLBFuncDesc
*pFDesc
;
8453 TLBCustData
*pCData
;
8457 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8458 debugstr_guid(guid
), pVarVal
);
8460 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8464 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8465 return TYPE_E_ELEMENTNOTFOUND
;
8467 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8469 return TYPE_E_ELEMENTNOTFOUND
;
8471 VariantInit(pVarVal
);
8472 VariantCopy(pVarVal
, &pCData
->data
);
8477 /* ITypeInfo2::GetVarCustData
8479 * Gets the custom data
8481 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8487 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8488 TLBCustData
*pCData
;
8489 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8491 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8493 if(index
>= This
->typeattr
.cVars
)
8494 return TYPE_E_ELEMENTNOTFOUND
;
8496 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8498 return TYPE_E_ELEMENTNOTFOUND
;
8500 VariantInit(pVarVal
);
8501 VariantCopy(pVarVal
, &pCData
->data
);
8506 /* ITypeInfo2::GetImplCustData
8508 * Gets the custom data
8510 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8516 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8517 TLBCustData
*pCData
;
8518 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8520 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8522 if(index
>= This
->typeattr
.cImplTypes
)
8523 return TYPE_E_ELEMENTNOTFOUND
;
8525 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8527 return TYPE_E_ELEMENTNOTFOUND
;
8529 VariantInit(pVarVal
);
8530 VariantCopy(pVarVal
, &pCData
->data
);
8535 /* ITypeInfo2::GetDocumentation2
8537 * Retrieves the documentation string, the complete Help file name and path,
8538 * the localization context to use, and the context ID for the library Help
8539 * topic in the Help file.
8542 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8546 BSTR
*pbstrHelpString
,
8547 DWORD
*pdwHelpStringContext
,
8548 BSTR
*pbstrHelpStringDll
)
8550 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8551 const TLBFuncDesc
*pFDesc
;
8552 const TLBVarDesc
*pVDesc
;
8553 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8554 "HelpStringContext(%p) HelpStringDll(%p)\n",
8555 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8556 pbstrHelpStringDll
);
8557 /* the help string should be obtained from the helpstringdll,
8558 * using the _DLLGetDocumentation function, based on the supplied
8559 * lcid. Nice to do sometime...
8561 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8563 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8564 if(pdwHelpStringContext
)
8565 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8566 if(pbstrHelpStringDll
)
8567 *pbstrHelpStringDll
=
8568 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8570 }else {/* for a member */
8571 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
8574 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8575 if(pdwHelpStringContext
)
8576 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8577 if(pbstrHelpStringDll
)
8578 *pbstrHelpStringDll
=
8579 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8582 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
8585 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8586 if(pdwHelpStringContext
)
8587 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8588 if(pbstrHelpStringDll
)
8589 *pbstrHelpStringDll
=
8590 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8594 return TYPE_E_ELEMENTNOTFOUND
;
8597 /* ITypeInfo2::GetAllCustData
8599 * Gets all custom data items for the Type info.
8602 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8604 CUSTDATA
*pCustData
)
8606 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8608 TRACE("%p %p\n", This
, pCustData
);
8610 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8613 /* ITypeInfo2::GetAllFuncCustData
8615 * Gets all custom data items for the specified Function
8618 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8621 CUSTDATA
*pCustData
)
8623 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8624 const TLBFuncDesc
*pFDesc
;
8628 TRACE("%p %u %p\n", This
, index
, pCustData
);
8630 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &pFDesc
, &hrefoffset
);
8634 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8637 /* ITypeInfo2::GetAllParamCustData
8639 * Gets all custom data items for the Functions
8642 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8643 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8645 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8646 const TLBFuncDesc
*pFDesc
;
8650 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8652 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8656 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8657 return TYPE_E_ELEMENTNOTFOUND
;
8659 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8662 /* ITypeInfo2::GetAllVarCustData
8664 * Gets all custom data items for the specified Variable
8667 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8668 UINT index
, CUSTDATA
*pCustData
)
8670 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8671 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8673 TRACE("%p %u %p\n", This
, index
, pCustData
);
8675 if(index
>= This
->typeattr
.cVars
)
8676 return TYPE_E_ELEMENTNOTFOUND
;
8678 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8681 /* ITypeInfo2::GetAllImplCustData
8683 * Gets all custom data items for the specified implementation type
8686 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8689 CUSTDATA
*pCustData
)
8691 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8692 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8694 TRACE("%p %u %p\n", This
, index
, pCustData
);
8696 if(index
>= This
->typeattr
.cImplTypes
)
8697 return TYPE_E_ELEMENTNOTFOUND
;
8699 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8702 static const ITypeInfo2Vtbl tinfvt
=
8705 ITypeInfo_fnQueryInterface
,
8707 ITypeInfo_fnRelease
,
8709 ITypeInfo_fnGetTypeAttr
,
8710 ITypeInfo_fnGetTypeComp
,
8711 ITypeInfo_fnGetFuncDesc
,
8712 ITypeInfo_fnGetVarDesc
,
8713 ITypeInfo_fnGetNames
,
8714 ITypeInfo_fnGetRefTypeOfImplType
,
8715 ITypeInfo_fnGetImplTypeFlags
,
8716 ITypeInfo_fnGetIDsOfNames
,
8718 ITypeInfo_fnGetDocumentation
,
8719 ITypeInfo_fnGetDllEntry
,
8720 ITypeInfo_fnGetRefTypeInfo
,
8721 ITypeInfo_fnAddressOfMember
,
8722 ITypeInfo_fnCreateInstance
,
8723 ITypeInfo_fnGetMops
,
8724 ITypeInfo_fnGetContainingTypeLib
,
8725 ITypeInfo_fnReleaseTypeAttr
,
8726 ITypeInfo_fnReleaseFuncDesc
,
8727 ITypeInfo_fnReleaseVarDesc
,
8729 ITypeInfo2_fnGetTypeKind
,
8730 ITypeInfo2_fnGetTypeFlags
,
8731 ITypeInfo2_fnGetFuncIndexOfMemId
,
8732 ITypeInfo2_fnGetVarIndexOfMemId
,
8733 ITypeInfo2_fnGetCustData
,
8734 ITypeInfo2_fnGetFuncCustData
,
8735 ITypeInfo2_fnGetParamCustData
,
8736 ITypeInfo2_fnGetVarCustData
,
8737 ITypeInfo2_fnGetImplTypeCustData
,
8738 ITypeInfo2_fnGetDocumentation2
,
8739 ITypeInfo2_fnGetAllCustData
,
8740 ITypeInfo2_fnGetAllFuncCustData
,
8741 ITypeInfo2_fnGetAllParamCustData
,
8742 ITypeInfo2_fnGetAllVarCustData
,
8743 ITypeInfo2_fnGetAllImplTypeCustData
,
8746 /******************************************************************************
8747 * CreateDispTypeInfo [OLEAUT32.31]
8749 * Build type information for an object so it can be called through an
8750 * IDispatch interface.
8753 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8754 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8757 * This call allows an objects methods to be accessed through IDispatch, by
8758 * building an ITypeInfo object that IDispatch can use to call through.
8760 HRESULT WINAPI
CreateDispTypeInfo(
8761 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8762 LCID lcid
, /* [I] Locale Id */
8763 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8765 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8766 ITypeLibImpl
*pTypeLibImpl
;
8767 unsigned int param
, func
;
8768 TLBFuncDesc
*pFuncDesc
;
8772 pTypeLibImpl
= TypeLibImpl_Constructor();
8773 if (!pTypeLibImpl
) return E_FAIL
;
8775 pTypeLibImpl
->TypeInfoCount
= 2;
8776 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8778 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8779 pTIIface
->pTypeLib
= pTypeLibImpl
;
8780 pTIIface
->index
= 0;
8781 pTIIface
->Name
= NULL
;
8782 pTIIface
->dwHelpContext
= -1;
8783 pTIIface
->guid
= NULL
;
8784 pTIIface
->typeattr
.lcid
= lcid
;
8785 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8786 pTIIface
->typeattr
.wMajorVerNum
= 0;
8787 pTIIface
->typeattr
.wMinorVerNum
= 0;
8788 pTIIface
->typeattr
.cbAlignment
= 2;
8789 pTIIface
->typeattr
.cbSizeInstance
= -1;
8790 pTIIface
->typeattr
.cbSizeVft
= -1;
8791 pTIIface
->typeattr
.cFuncs
= 0;
8792 pTIIface
->typeattr
.cImplTypes
= 0;
8793 pTIIface
->typeattr
.cVars
= 0;
8794 pTIIface
->typeattr
.wTypeFlags
= 0;
8795 pTIIface
->hreftype
= 0;
8797 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8798 pFuncDesc
= pTIIface
->funcdescs
;
8799 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8800 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8801 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8802 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8803 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8804 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8805 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8806 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8807 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8808 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8809 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8810 pFuncDesc
->funcdesc
.cScodes
= 0;
8811 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8812 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8813 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8814 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8815 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8816 md
->cArgs
* sizeof(ELEMDESC
));
8817 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8818 for(param
= 0; param
< md
->cArgs
; param
++) {
8819 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8820 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8822 pFuncDesc
->helpcontext
= 0;
8823 pFuncDesc
->HelpStringContext
= 0;
8824 pFuncDesc
->HelpString
= NULL
;
8825 pFuncDesc
->Entry
= NULL
;
8826 list_init(&pFuncDesc
->custdata_list
);
8827 pTIIface
->typeattr
.cFuncs
++;
8831 dump_TypeInfo(pTIIface
);
8833 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8834 pTIClass
->pTypeLib
= pTypeLibImpl
;
8835 pTIClass
->index
= 1;
8836 pTIClass
->Name
= NULL
;
8837 pTIClass
->dwHelpContext
= -1;
8838 pTIClass
->guid
= NULL
;
8839 pTIClass
->typeattr
.lcid
= lcid
;
8840 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8841 pTIClass
->typeattr
.wMajorVerNum
= 0;
8842 pTIClass
->typeattr
.wMinorVerNum
= 0;
8843 pTIClass
->typeattr
.cbAlignment
= 2;
8844 pTIClass
->typeattr
.cbSizeInstance
= -1;
8845 pTIClass
->typeattr
.cbSizeVft
= -1;
8846 pTIClass
->typeattr
.cFuncs
= 0;
8847 pTIClass
->typeattr
.cImplTypes
= 1;
8848 pTIClass
->typeattr
.cVars
= 0;
8849 pTIClass
->typeattr
.wTypeFlags
= 0;
8850 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8852 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8854 ref
= heap_alloc_zero(sizeof(*ref
));
8855 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8856 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8858 dump_TypeInfo(pTIClass
);
8860 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8862 ITypeInfo_AddRef(*pptinfo
);
8863 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8869 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8871 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8873 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8876 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8878 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8880 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8883 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8885 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8887 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8890 static HRESULT WINAPI
ITypeComp_fnBind(
8895 ITypeInfo
** ppTInfo
,
8896 DESCKIND
* pDescKind
,
8899 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8900 const TLBFuncDesc
*pFDesc
;
8901 const TLBVarDesc
*pVDesc
;
8902 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8905 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8907 *pDescKind
= DESCKIND_NONE
;
8908 pBindPtr
->lpfuncdesc
= NULL
;
8911 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8912 pFDesc
= &This
->funcdescs
[fdc
];
8913 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8914 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8917 /* name found, but wrong flags */
8918 hr
= TYPE_E_TYPEMISMATCH
;
8922 if (fdc
< This
->typeattr
.cFuncs
)
8924 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8926 &pBindPtr
->lpfuncdesc
,
8927 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8930 *pDescKind
= DESCKIND_FUNCDESC
;
8931 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8932 ITypeInfo_AddRef(*ppTInfo
);
8935 pVDesc
= TLB_get_vardesc_by_name(This
, szName
);
8937 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8940 *pDescKind
= DESCKIND_VARDESC
;
8941 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8942 ITypeInfo_AddRef(*ppTInfo
);
8947 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8948 /* recursive search */
8952 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8955 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8956 ITypeInfo_Release(pTInfo
);
8960 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8961 ITypeComp_Release(pTComp
);
8962 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8963 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8965 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8966 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8967 SysFreeString((BSTR
)tmp
);
8971 WARN("Could not search inherited interface!\n");
8973 if (hr
== DISP_E_MEMBERNOTFOUND
)
8975 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8979 static HRESULT WINAPI
ITypeComp_fnBindType(
8983 ITypeInfo
** ppTInfo
,
8984 ITypeComp
** ppTComp
)
8986 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8988 /* strange behaviour (does nothing) but like the
8991 if (!ppTInfo
|| !ppTComp
)
9000 static const ITypeCompVtbl tcompvt
=
9003 ITypeComp_fnQueryInterface
,
9005 ITypeComp_fnRelease
,
9008 ITypeComp_fnBindType
9011 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
9012 ICreateTypeLib2
** ppctlib
)
9017 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
9019 if (!szFile
) return E_INVALIDARG
;
9021 This
= TypeLibImpl_Constructor();
9023 return E_OUTOFMEMORY
;
9025 This
->lcid
= GetSystemDefaultLCID();
9026 This
->syskind
= syskind
;
9027 This
->ptr_size
= get_ptr_size(syskind
);
9029 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
9031 ITypeLib2_Release(&This
->ITypeLib2_iface
);
9032 return E_OUTOFMEMORY
;
9034 lstrcpyW(This
->path
, szFile
);
9036 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
9037 ITypeLib2_Release(&This
->ITypeLib2_iface
);
9041 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
9042 REFIID riid
, void **object
)
9044 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9046 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
9049 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
9051 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9053 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
9056 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
9058 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9060 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
9063 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
9064 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
9066 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9067 ITypeInfoImpl
*info
;
9070 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
9072 if (!ctinfo
|| !name
)
9073 return E_INVALIDARG
;
9075 info
= TLB_get_typeinfo_by_name(This
, name
);
9077 return TYPE_E_NAMECONFLICT
;
9079 if (This
->typeinfos
)
9080 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
9081 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
9083 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
9085 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
9087 info
->pTypeLib
= This
;
9088 info
->Name
= TLB_append_str(&This
->name_list
, name
);
9089 info
->index
= This
->TypeInfoCount
;
9090 info
->typeattr
.typekind
= kind
;
9091 info
->typeattr
.cbAlignment
= 4;
9093 switch (info
->typeattr
.typekind
) {
9095 case TKIND_INTERFACE
:
9096 case TKIND_DISPATCH
:
9098 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
9102 info
->typeattr
.cbSizeInstance
= 0;
9105 info
->typeattr
.cbSizeInstance
= 2;
9108 info
->typeattr
.cbSizeInstance
= -0x75;
9111 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
9112 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
9116 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
9117 &IID_ICreateTypeInfo
, (void **)ctinfo
);
9119 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
9123 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
9125 ++This
->TypeInfoCount
;
9130 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
9133 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9135 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
9138 return E_INVALIDARG
;
9140 This
->Name
= TLB_append_str(&This
->name_list
, name
);
9145 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
9146 WORD majorVerNum
, WORD minorVerNum
)
9148 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9150 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
9152 This
->ver_major
= majorVerNum
;
9153 This
->ver_minor
= minorVerNum
;
9158 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
9161 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9163 TRACE("%p %s\n", This
, debugstr_guid(guid
));
9165 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
9170 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
9173 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9175 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
9178 return E_INVALIDARG
;
9180 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
9185 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
9186 LPOLESTR helpFileName
)
9188 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9190 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
9193 return E_INVALIDARG
;
9195 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
9200 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
9203 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9205 TRACE("%p %d\n", This
, helpContext
);
9207 This
->dwHelpContext
= helpContext
;
9212 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
9215 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9217 TRACE("%p %x\n", This
, lcid
);
9219 This
->set_lcid
= lcid
;
9224 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9227 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9229 TRACE("%p %x\n", This
, libFlags
);
9231 This
->libflags
= libFlags
;
9236 typedef struct tagWMSFT_SegContents
{
9239 } WMSFT_SegContents
;
9241 typedef struct tagWMSFT_TLBFile
{
9243 WMSFT_SegContents typeinfo_seg
;
9244 WMSFT_SegContents impfile_seg
;
9245 WMSFT_SegContents impinfo_seg
;
9246 WMSFT_SegContents ref_seg
;
9247 WMSFT_SegContents guidhash_seg
;
9248 WMSFT_SegContents guid_seg
;
9249 WMSFT_SegContents namehash_seg
;
9250 WMSFT_SegContents name_seg
;
9251 WMSFT_SegContents string_seg
;
9252 WMSFT_SegContents typdesc_seg
;
9253 WMSFT_SegContents arraydesc_seg
;
9254 WMSFT_SegContents custdata_seg
;
9255 WMSFT_SegContents cdguids_seg
;
9257 WMSFT_SegContents aux_seg
;
9260 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9261 WMSFT_TLBFile
*file
)
9267 file
->string_seg
.len
= 0;
9268 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9271 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9273 return E_UNEXPECTED
;
9275 size
+= sizeof(INT16
);
9277 size
= (size
+ 4) & ~0x3;
9281 file
->string_seg
.len
+= size
;
9283 /* temporarily use str->offset to store the length of the aligned,
9284 * converted string */
9288 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
9291 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9294 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9295 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9297 heap_free(file
->string_seg
.data
);
9298 return E_UNEXPECTED
;
9301 *((INT16
*)data
) = size
;
9303 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9307 str
->offset
= last_offs
;
9314 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9315 WMSFT_TLBFile
*file
)
9320 MSFT_NameIntro
*last_intro
= NULL
;
9322 file
->header
.nametablecount
= 0;
9323 file
->header
.nametablechars
= 0;
9325 file
->name_seg
.len
= 0;
9326 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9329 size
= lstrlenW(str
->str
);
9330 file
->header
.nametablechars
+= size
;
9331 file
->header
.nametablecount
++;
9333 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9335 return E_UNEXPECTED
;
9337 size
+= sizeof(MSFT_NameIntro
);
9339 size
= (size
+ 4) & ~0x3;
9343 file
->name_seg
.len
+= size
;
9345 /* temporarily use str->offset to store the length of the aligned,
9346 * converted string */
9350 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9351 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
9354 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9356 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9358 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9359 data
+ sizeof(MSFT_NameIntro
),
9360 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9362 heap_free(file
->name_seg
.data
);
9363 return E_UNEXPECTED
;
9365 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9367 intro
->hreftype
= -1; /* TODO? */
9368 intro
->namelen
= size
& 0xFF;
9369 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9370 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9371 intro
->namelen
|= hash
<< 16;
9372 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9373 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9375 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9376 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9378 /* update str->offset to actual value to use in other
9379 * compilation functions that require positions within
9380 * the string table */
9384 str
->offset
= last_offs
;
9389 last_intro
->hreftype
= 0; /* last one is 0? */
9394 static inline int hash_guid(GUID
*guid
)
9398 for (i
= 0; i
< 8; i
++)
9399 hash
^= ((const short *)guid
)[i
];
9404 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9407 MSFT_GuidEntry
*entry
;
9409 int hash_key
, *guidhashtab
;
9411 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9412 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9414 entry
= file
->guid_seg
.data
;
9416 guidhashtab
= file
->guidhash_seg
.data
;
9417 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9418 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9419 entry
->hreftype
= guid
->hreftype
;
9421 hash_key
= hash_guid(&guid
->guid
);
9422 entry
->next_hash
= guidhashtab
[hash_key
];
9423 guidhashtab
[hash_key
] = offs
;
9425 guid
->offset
= offs
;
9426 offs
+= sizeof(MSFT_GuidEntry
);
9433 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9436 VARTYPE arg_type
= V_VT(value
);
9439 DWORD ret
= file
->custdata_seg
.len
;
9441 if(arg_type
== VT_INT
)
9443 if(arg_type
== VT_UINT
)
9447 if(V_VT(value
) != arg_type
) {
9448 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9450 ERR("VariantChangeType failed: %08x\n", hres
);
9455 /* Check if default value can be stored in-place */
9460 if(V_UI4(&v
) > 0x3ffffff)
9473 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9476 /* have to allocate space in custdata_seg */
9485 /* Construct the data to be allocated */
9488 if(file
->custdata_seg
.data
){
9489 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9490 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9491 file
->custdata_seg
.len
+= sizeof(int) * 2;
9493 file
->custdata_seg
.len
= sizeof(int) * 2;
9494 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9497 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9498 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9500 /* TODO: Check if the encoded data is already present in custdata_seg */
9506 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9509 if(file
->custdata_seg
.data
){
9510 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9511 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9512 file
->custdata_seg
.len
+= len
;
9514 file
->custdata_seg
.len
= len
;
9515 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9518 *((unsigned short *)data
) = V_VT(value
);
9519 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9520 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9521 if(V_BSTR(&v
)[i
] <= 0x7f)
9522 data
[i
+6] = V_BSTR(&v
)[i
];
9526 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9527 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9530 /* TODO: Check if the encoded data is already present in custdata_seg */
9535 FIXME("Argument type not yet handled\n");
9540 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9542 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9544 DWORD offs
= file
->arraydesc_seg
.len
;
9548 /* TODO: we should check for duplicates, but that's harder because each
9549 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9550 * at the library-level) */
9552 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9553 if(!file
->arraydesc_seg
.data
)
9554 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9556 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9557 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9559 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9560 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9561 for(i
= 0; i
< desc
->cDims
; ++i
){
9562 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9563 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9569 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9575 VARTYPE vt
, subtype
;
9586 vt
= desc
->vt
& VT_TYPEMASK
;
9588 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9590 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9591 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9593 *out_size
+= 2 * sizeof(DWORD
);
9594 }else if(vt
== VT_CARRAY
){
9595 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9596 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9598 }else if(vt
== VT_USERDEFINED
){
9599 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9600 encoded
[1] = desc
->u
.hreftype
;
9601 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9603 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9621 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9624 data
= file
->typdesc_seg
.data
;
9625 while(offs
< file
->typdesc_seg
.len
){
9626 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9628 offs
+= sizeof(encoded
);
9631 file
->typdesc_seg
.len
+= sizeof(encoded
);
9632 if(!file
->typdesc_seg
.data
)
9633 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9635 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9637 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9642 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9644 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9645 DWORD ret
= cdguids_seg
->len
, offs
;
9646 MSFT_CDGuid
*cdguid
;
9649 if(list_empty(custdata_list
))
9652 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9653 if(!cdguids_seg
->data
){
9654 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9656 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9657 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9660 offs
= ret
+ sizeof(MSFT_CDGuid
);
9661 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9662 cdguid
->GuidOffset
= cd
->guid
->offset
;
9663 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9664 cdguid
->next
= offs
;
9665 offs
+= sizeof(MSFT_CDGuid
);
9675 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9676 WMSFT_TLBFile
*file
)
9678 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9679 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9680 MSFT_VarRecord
*varrecord
;
9681 MSFT_FuncRecord
*funcrecord
;
9683 DWORD
*name
, *offsets
, offs
;
9685 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9686 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9688 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9690 /* optional fields */
9691 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9692 if(!list_empty(&desc
->custdata_list
))
9693 recorded_size
+= 7 * sizeof(INT
);
9694 else if(desc
->HelpStringContext
!= 0)
9695 recorded_size
+= 6 * sizeof(INT
);
9697 else if(desc
->Entry
)
9698 recorded_size
+= 3 * sizeof(INT
);
9699 else if(desc
->HelpString
)
9700 recorded_size
+= 2 * sizeof(INT
);
9701 else if(desc
->helpcontext
)
9702 recorded_size
+= sizeof(INT
);
9704 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9706 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9707 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9708 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9713 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9716 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9717 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9719 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9721 /* optional fields */
9722 if(desc
->HelpStringContext
!= 0)
9723 recorded_size
+= 5 * sizeof(INT
);
9724 else if(!list_empty(&desc
->custdata_list
))
9725 recorded_size
+= 4 * sizeof(INT
);
9727 else if(desc
->HelpString
)
9728 recorded_size
+= 2 * sizeof(INT
);
9729 else if(desc
->HelpContext
!= 0)
9730 recorded_size
+= sizeof(INT
);
9732 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9735 if(!recorded_size
&& !extra_size
)
9738 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9740 aux_seg
->len
+= recorded_size
+ extra_size
;
9742 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9745 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9747 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9749 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9751 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9754 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9755 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9756 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9757 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9759 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9760 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9761 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9762 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9765 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9770 * ^has_param_defaults
9771 * ^oEntry_is_intresource
9773 funcrecord
->FKCCIC
=
9774 desc
->funcdesc
.funckind
|
9775 (desc
->funcdesc
.invkind
<< 3) |
9776 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9777 (desc
->funcdesc
.callconv
<< 8);
9779 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9780 funcrecord
->FKCCIC
|= 0x2000;
9782 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9783 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9784 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9785 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9788 if(paramdefault_size
> 0)
9789 funcrecord
->FKCCIC
|= 0x1000;
9791 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9792 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9794 /* optional fields */
9796 if(!list_empty(&desc
->custdata_list
)){
9797 size
+= 7 * sizeof(INT
);
9798 funcrecord
->HelpContext
= desc
->helpcontext
;
9799 if(desc
->HelpString
)
9800 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9802 funcrecord
->oHelpString
= -1;
9804 funcrecord
->oEntry
= -1;
9805 else if(IS_INTRESOURCE(desc
->Entry
))
9806 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9808 funcrecord
->oEntry
= desc
->Entry
->offset
;
9809 funcrecord
->res9
= -1;
9810 funcrecord
->resA
= -1;
9811 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9812 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9813 }else if(desc
->HelpStringContext
!= 0){
9814 size
+= 6 * sizeof(INT
);
9815 funcrecord
->HelpContext
= desc
->helpcontext
;
9816 if(desc
->HelpString
)
9817 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9819 funcrecord
->oHelpString
= -1;
9821 funcrecord
->oEntry
= -1;
9822 else if(IS_INTRESOURCE(desc
->Entry
))
9823 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9825 funcrecord
->oEntry
= desc
->Entry
->offset
;
9826 funcrecord
->res9
= -1;
9827 funcrecord
->resA
= -1;
9828 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9829 }else if(desc
->Entry
){
9830 size
+= 3 * sizeof(INT
);
9831 funcrecord
->HelpContext
= desc
->helpcontext
;
9832 if(desc
->HelpString
)
9833 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9835 funcrecord
->oHelpString
= -1;
9837 funcrecord
->oEntry
= -1;
9838 else if(IS_INTRESOURCE(desc
->Entry
))
9839 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9841 funcrecord
->oEntry
= desc
->Entry
->offset
;
9842 }else if(desc
->HelpString
){
9843 size
+= 2 * sizeof(INT
);
9844 funcrecord
->HelpContext
= desc
->helpcontext
;
9845 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9846 }else if(desc
->helpcontext
){
9847 size
+= sizeof(INT
);
9848 funcrecord
->HelpContext
= desc
->helpcontext
;
9851 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9852 size
+= paramdefault_size
;
9854 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9855 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9857 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9858 if(desc
->pParamDesc
[j
].Name
)
9859 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9862 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9864 if(paramdefault_size
){
9865 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9866 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9867 else if(paramdefault_size
)
9872 size
+= sizeof(MSFT_ParameterInfo
);
9875 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9881 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9884 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9885 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9886 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9887 DWORD size
= 5 * sizeof(INT
);
9889 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9890 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9891 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9892 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9894 if(desc
->vardesc
.varkind
== VAR_CONST
){
9895 varrecord
->vardescsize
+= sizeof(VARIANT
);
9896 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9898 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9901 if(desc
->HelpStringContext
!= 0){
9902 size
+= 5 * sizeof(INT
);
9903 varrecord
->HelpContext
= desc
->HelpContext
;
9904 if(desc
->HelpString
)
9905 varrecord
->HelpString
= desc
->HelpString
->offset
;
9907 varrecord
->HelpString
= -1;
9908 varrecord
->res9
= -1;
9909 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9910 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9911 }else if(!list_empty(&desc
->custdata_list
)){
9912 size
+= 4 * sizeof(INT
);
9913 varrecord
->HelpContext
= desc
->HelpContext
;
9914 if(desc
->HelpString
)
9915 varrecord
->HelpString
= desc
->HelpString
->offset
;
9917 varrecord
->HelpString
= -1;
9918 varrecord
->res9
= -1;
9919 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9920 }else if(desc
->HelpString
){
9921 size
+= 2 * sizeof(INT
);
9922 varrecord
->HelpContext
= desc
->HelpContext
;
9923 if(desc
->HelpString
)
9924 varrecord
->HelpString
= desc
->HelpString
->offset
;
9926 varrecord
->HelpString
= -1;
9927 }else if(desc
->HelpContext
!= 0){
9928 size
+= sizeof(INT
);
9929 varrecord
->HelpContext
= desc
->HelpContext
;
9932 varrecord
->Info
= size
| (i
<< 16);
9938 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9941 memid
= (MEMBERID
*)varrecord
;
9942 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9943 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9944 *memid
= desc
->funcdesc
.memid
;
9947 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9948 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9949 *memid
= desc
->vardesc
.memid
;
9953 name
= (UINT
*)memid
;
9954 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9955 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9957 *name
= desc
->Name
->offset
;
9962 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9963 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9965 *name
= desc
->Name
->offset
;
9974 typedef struct tagWMSFT_RefChunk
{
9981 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9983 DWORD offs
= file
->ref_seg
.len
, i
;
9984 WMSFT_RefChunk
*chunk
;
9986 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9987 if(!file
->ref_seg
.data
)
9988 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9990 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9992 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9994 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9995 chunk
->href
= info
->impltypes
[i
].hRef
;
9996 chunk
->res04
= info
->impltypes
[i
].implflags
;
9998 if(i
< info
->typeattr
.cImplTypes
- 1)
9999 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
10008 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
10012 size
= sizeof(MSFT_TypeInfoBase
);
10015 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
10016 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
10017 base
->typekind
= TKIND_DISPATCH
;
10019 base
->typekind
= info
->typeattr
.typekind
;
10020 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
10021 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
10022 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
10027 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
10033 base
->posguid
= info
->guid
->offset
;
10035 base
->posguid
= -1;
10036 base
->flags
= info
->typeattr
.wTypeFlags
;
10038 base
->NameOffset
= info
->Name
->offset
;
10040 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
10041 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
10043 base
->NameOffset
= -1;
10045 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
10046 if(info
->DocString
)
10047 base
->docstringoffs
= info
->DocString
->offset
;
10049 base
->docstringoffs
= -1;
10050 base
->helpstringcontext
= info
->dwHelpStringContext
;
10051 base
->helpcontext
= info
->dwHelpContext
;
10052 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
10053 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
10054 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
10055 base
->size
= info
->typeattr
.cbSizeInstance
;
10056 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
10057 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
10058 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
10059 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
10060 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
10062 base
->datatype1
= info
->DllName
->offset
;
10064 base
->datatype1
= -1;
10066 if(info
->typeattr
.cImplTypes
> 0)
10067 base
->datatype1
= info
->impltypes
[0].hRef
;
10069 base
->datatype1
= -1;
10071 base
->datatype2
= index
; /* FIXME: i think there's more here */
10079 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
10083 file
->typeinfo_seg
.len
= 0;
10084 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10085 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
10086 *junk
= file
->typeinfo_seg
.len
;
10088 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
10091 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
10092 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
10094 file
->aux_seg
.len
= 0;
10095 file
->aux_seg
.data
= NULL
;
10097 file
->typeinfo_seg
.len
= 0;
10098 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10099 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
10100 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
10101 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
10105 typedef struct tagWMSFT_ImpFile
{
10111 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10114 WMSFT_ImpFile
*impfile
;
10116 DWORD last_offs
= 0;
10118 file
->impfile_seg
.len
= 0;
10119 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10123 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10127 path
= implib
->name
;
10128 size
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
), NULL
, 0, NULL
, NULL
);
10130 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10133 size
+= sizeof(INT16
);
10135 size
= (size
+ 4) & ~0x3;
10139 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
10142 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
10144 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10145 int strlen
= 0, size
;
10147 impfile
= (WMSFT_ImpFile
*)data
;
10148 impfile
->guid_offs
= implib
->guid
->offset
;
10149 impfile
->lcid
= implib
->lcid
;
10150 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
10152 data
+= sizeof(WMSFT_ImpFile
);
10155 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10159 path
= implib
->name
;
10160 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
),
10161 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
10163 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10166 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
10168 size
= strlen
+ sizeof(INT16
);
10170 size
= (size
+ 4) & ~0x3;
10173 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
10176 implib
->offset
= last_offs
;
10177 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
10181 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10183 MSFT_ImpInfo
*info
;
10184 TLBRefType
*ref_type
;
10187 WMSFT_compile_impfile(This
, file
);
10189 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
10190 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
10192 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
10193 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
10194 if(ref_type
->index
== TLB_REF_USE_GUID
){
10195 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
10196 info
->oGuid
= ref_type
->guid
->offset
;
10198 info
->oGuid
= ref_type
->index
;
10199 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
10205 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10207 file
->guidhash_seg
.len
= 0x80;
10208 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
10209 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
10212 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10214 file
->namehash_seg
.len
= 0x200;
10215 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
10216 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
10219 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
10221 if(contents
&& contents
->len
){
10222 segdir
->offset
= *running_offset
;
10223 segdir
->length
= contents
->len
;
10224 *running_offset
+= segdir
->length
;
10226 segdir
->offset
= -1;
10227 segdir
->length
= 0;
10230 /* TODO: do these ever change? */
10231 segdir
->res08
= -1;
10232 segdir
->res0c
= 0xf;
10235 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10239 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10242 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10246 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10248 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10249 base
->memoffset
+= file_len
;
10256 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10258 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
10259 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
10260 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
10261 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
10262 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
10263 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
10264 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
10265 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
10266 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
10267 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
10268 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
10269 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
10270 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
10271 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
10274 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10276 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10277 WMSFT_TLBFile file
;
10278 DWORD written
, junk_size
, junk_offs
, running_offset
;
10285 TRACE("%p\n", This
);
10287 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10288 if(This
->typeinfos
[i
]->needs_layout
)
10289 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10291 memset(&file
, 0, sizeof(file
));
10293 file
.header
.magic1
= 0x5446534D;
10294 file
.header
.magic2
= 0x00010002;
10295 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10296 file
.header
.lcid2
= This
->set_lcid
;
10297 file
.header
.varflags
= 0x40 | This
->syskind
;
10298 if (This
->HelpFile
)
10299 file
.header
.varflags
|= 0x10;
10300 if (This
->HelpStringDll
)
10301 file
.header
.varflags
|= HELPDLLFLAG
;
10302 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10303 file
.header
.flags
= This
->libflags
;
10304 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10305 file
.header
.helpcontext
= This
->dwHelpContext
;
10306 file
.header
.res44
= 0x20;
10307 file
.header
.res48
= 0x80;
10308 file
.header
.dispatchpos
= This
->dispatch_href
;
10310 WMSFT_compile_namehash(This
, &file
);
10311 /* do name and string compilation to get offsets for other compilations */
10312 hres
= WMSFT_compile_names(This
, &file
);
10314 WMSFT_free_file(&file
);
10318 hres
= WMSFT_compile_strings(This
, &file
);
10320 WMSFT_free_file(&file
);
10324 WMSFT_compile_guidhash(This
, &file
);
10325 hres
= WMSFT_compile_guids(This
, &file
);
10327 WMSFT_free_file(&file
);
10332 file
.header
.helpfile
= This
->HelpFile
->offset
;
10334 file
.header
.helpfile
= -1;
10336 if(This
->DocString
)
10337 file
.header
.helpstring
= This
->DocString
->offset
;
10339 file
.header
.helpstring
= -1;
10341 /* do some more segment compilation */
10342 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10343 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10346 file
.header
.NameOffset
= This
->Name
->offset
;
10348 file
.header
.NameOffset
= -1;
10350 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10353 file
.header
.posguid
= This
->guid
->offset
;
10355 file
.header
.posguid
= -1;
10357 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10358 if(file
.header
.varflags
& HELPDLLFLAG
)
10359 junk_size
+= sizeof(DWORD
);
10361 junk
= heap_alloc_zero(junk_size
);
10362 if(file
.header
.varflags
& HELPDLLFLAG
){
10363 *junk
= This
->HelpStringDll
->offset
;
10372 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10373 WMSFT_compile_impinfo(This
, &file
);
10375 running_offset
= 0;
10377 TRACE("header at: 0x%x\n", running_offset
);
10378 running_offset
+= sizeof(file
.header
);
10380 TRACE("junk at: 0x%x\n", running_offset
);
10381 running_offset
+= junk_size
;
10383 TRACE("segdir at: 0x%x\n", running_offset
);
10384 running_offset
+= sizeof(file
.segdir
);
10386 TRACE("typeinfo at: 0x%x\n", running_offset
);
10387 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10389 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10390 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10392 TRACE("guidtab at: 0x%x\n", running_offset
);
10393 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10395 TRACE("reftab at: 0x%x\n", running_offset
);
10396 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10398 TRACE("impinfo at: 0x%x\n", running_offset
);
10399 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10401 TRACE("impfiles at: 0x%x\n", running_offset
);
10402 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10404 TRACE("namehashtab at: 0x%x\n", running_offset
);
10405 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10407 TRACE("nametab at: 0x%x\n", running_offset
);
10408 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10410 TRACE("stringtab at: 0x%x\n", running_offset
);
10411 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10413 TRACE("typdesc at: 0x%x\n", running_offset
);
10414 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10416 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10417 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10419 TRACE("custdata at: 0x%x\n", running_offset
);
10420 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10422 TRACE("cdguids at: 0x%x\n", running_offset
);
10423 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10425 TRACE("res0e at: 0x%x\n", running_offset
);
10426 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10428 TRACE("res0f at: 0x%x\n", running_offset
);
10429 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10431 TRACE("aux_seg at: 0x%x\n", running_offset
);
10433 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10435 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10436 FILE_ATTRIBUTE_NORMAL
, 0);
10437 if (outfile
== INVALID_HANDLE_VALUE
){
10438 WMSFT_free_file(&file
);
10440 return TYPE_E_IOERROR
;
10443 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10445 WMSFT_free_file(&file
);
10446 CloseHandle(outfile
);
10448 return TYPE_E_IOERROR
;
10451 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10454 WMSFT_free_file(&file
);
10455 CloseHandle(outfile
);
10456 return TYPE_E_IOERROR
;
10459 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10461 WMSFT_free_file(&file
);
10462 CloseHandle(outfile
);
10463 return TYPE_E_IOERROR
;
10466 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10467 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10468 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10469 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10470 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10471 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10472 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10473 WMSFT_write_segment(outfile
, &file
.name_seg
);
10474 WMSFT_write_segment(outfile
, &file
.string_seg
);
10475 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10476 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10477 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10478 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10479 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10481 WMSFT_free_file(&file
);
10483 CloseHandle(outfile
);
10488 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10491 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10492 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10496 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10497 REFGUID guid
, VARIANT
*varVal
)
10499 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10502 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10504 if (!guid
|| !varVal
)
10505 return E_INVALIDARG
;
10507 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10509 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10512 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10513 ULONG helpStringContext
)
10515 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10516 FIXME("%p %u - stub\n", This
, helpStringContext
);
10520 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10523 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10524 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10527 return E_INVALIDARG
;
10529 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10534 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10535 ICreateTypeLib2_fnQueryInterface
,
10536 ICreateTypeLib2_fnAddRef
,
10537 ICreateTypeLib2_fnRelease
,
10538 ICreateTypeLib2_fnCreateTypeInfo
,
10539 ICreateTypeLib2_fnSetName
,
10540 ICreateTypeLib2_fnSetVersion
,
10541 ICreateTypeLib2_fnSetGuid
,
10542 ICreateTypeLib2_fnSetDocString
,
10543 ICreateTypeLib2_fnSetHelpFileName
,
10544 ICreateTypeLib2_fnSetHelpContext
,
10545 ICreateTypeLib2_fnSetLcid
,
10546 ICreateTypeLib2_fnSetLibFlags
,
10547 ICreateTypeLib2_fnSaveAllChanges
,
10548 ICreateTypeLib2_fnDeleteTypeInfo
,
10549 ICreateTypeLib2_fnSetCustData
,
10550 ICreateTypeLib2_fnSetHelpStringContext
,
10551 ICreateTypeLib2_fnSetHelpStringDll
10554 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10555 REFIID riid
, void **object
)
10557 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10559 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10562 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10564 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10566 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10569 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10571 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10573 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10576 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10579 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10581 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10583 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10588 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10591 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10595 TRACE("%p %x\n", This
, typeFlags
);
10597 if (typeFlags
& TYPEFLAG_FDUAL
) {
10599 ITypeInfo
*dispatch
;
10603 hres
= LoadTypeLib(L
"stdole2.tlb", &stdole
);
10607 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10608 ITypeLib_Release(stdole
);
10612 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10613 ITypeInfo_Release(dispatch
);
10618 old_flags
= This
->typeattr
.wTypeFlags
;
10619 This
->typeattr
.wTypeFlags
= typeFlags
;
10621 hres
= ICreateTypeInfo2_LayOut(iface
);
10622 if (FAILED(hres
)) {
10623 This
->typeattr
.wTypeFlags
= old_flags
;
10630 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10633 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10635 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10638 return E_INVALIDARG
;
10640 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10645 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10648 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10650 TRACE("%p %d\n", This
, helpContext
);
10652 This
->dwHelpContext
= helpContext
;
10657 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10658 WORD majorVerNum
, WORD minorVerNum
)
10660 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10662 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10664 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10665 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10670 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10671 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10673 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10675 ITypeLib
*container
;
10676 TLBRefType
*ref_type
;
10678 TYPEATTR
*typeattr
;
10682 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10684 if (!typeInfo
|| !refType
)
10685 return E_INVALIDARG
;
10687 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10691 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10692 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10694 ITypeLib_Release(container
);
10696 *refType
= target
->hreftype
;
10701 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10702 if (FAILED(hres
)) {
10703 ITypeLib_Release(container
);
10707 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10708 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10709 implib
->lcid
== libattr
->lcid
&&
10710 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10711 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10715 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10716 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10718 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10719 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10720 implib
->name
= SysAllocString(our_container
->path
);
10722 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10723 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10725 implib
->name
= NULL
;
10726 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10730 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10731 implib
->lcid
= libattr
->lcid
;
10732 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10733 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10735 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10738 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10739 ITypeLib_Release(container
);
10741 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10746 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10747 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10748 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10749 ref_type
->tkind
== typeattr
->typekind
)
10754 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10755 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10757 ref_type
->tkind
= typeattr
->typekind
;
10758 ref_type
->pImpTLInfo
= implib
;
10759 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10761 ref_type
->index
= TLB_REF_USE_GUID
;
10763 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10765 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10768 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10770 *refType
= ref_type
->reference
| 0x1;
10772 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10773 This
->pTypeLib
->dispatch_href
= *refType
;
10778 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10779 UINT index
, FUNCDESC
*funcDesc
)
10781 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10782 TLBFuncDesc tmp_func_desc
, *func_desc
;
10787 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10789 if (!funcDesc
|| funcDesc
->oVft
& 3)
10790 return E_INVALIDARG
;
10792 switch (This
->typeattr
.typekind
) {
10794 if (funcDesc
->funckind
!= FUNC_STATIC
)
10795 return TYPE_E_BADMODULEKIND
;
10797 case TKIND_DISPATCH
:
10798 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10799 return TYPE_E_BADMODULEKIND
;
10802 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10803 return TYPE_E_BADMODULEKIND
;
10806 if (index
> This
->typeattr
.cFuncs
)
10807 return TYPE_E_ELEMENTNOTFOUND
;
10809 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10810 !funcDesc
->cParams
)
10811 return TYPE_E_INCONSISTENTPROPFUNCS
;
10814 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10815 funcDesc
->oVft
% 8 != 0)
10816 return E_INVALIDARG
;
10819 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10820 TLBFuncDesc_Constructor(&tmp_func_desc
);
10822 tmp_func_desc
.funcdesc
= *funcDesc
;
10824 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10825 tmp_func_desc
.funcdesc
.oVft
|= 1;
10827 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10828 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10829 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10831 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10832 tmp_func_desc
.funcdesc
.cScodes
= 0;
10835 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10836 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10837 buf_size
+= sizeof(ELEMDESC
);
10838 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10840 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10841 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10843 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10844 if (FAILED(hres
)) {
10845 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10846 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10850 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10851 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10852 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10853 if (FAILED(hres
)) {
10854 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10855 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10858 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10859 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10860 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10861 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10862 if (FAILED(hres
)) {
10863 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10864 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10870 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10872 if (This
->funcdescs
) {
10873 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10874 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10876 if (index
< This
->typeattr
.cFuncs
) {
10877 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10878 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10879 func_desc
= This
->funcdescs
+ index
;
10881 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10883 /* move custdata lists to the new memory location */
10884 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10886 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
10889 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10891 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10892 list_init(&func_desc
->custdata_list
);
10894 ++This
->typeattr
.cFuncs
;
10896 This
->needs_layout
= TRUE
;
10901 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10902 UINT index
, HREFTYPE refType
)
10904 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10905 TLBImplType
*impl_type
;
10908 TRACE("%p %u %d\n", This
, index
, refType
);
10910 switch(This
->typeattr
.typekind
){
10911 case TKIND_COCLASS
: {
10913 FIXME("Unhandled index: -1\n");
10917 if(index
!= This
->typeattr
.cImplTypes
)
10918 return TYPE_E_ELEMENTNOTFOUND
;
10922 case TKIND_INTERFACE
:
10923 case TKIND_DISPATCH
:
10924 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10925 return TYPE_E_ELEMENTNOTFOUND
;
10928 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10932 if (This
->impltypes
){
10935 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10936 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10938 if (index
< This
->typeattr
.cImplTypes
) {
10939 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10940 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10941 impl_type
= This
->impltypes
+ index
;
10943 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10945 /* move custdata lists to the new memory location */
10946 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10948 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
10951 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10953 memset(impl_type
, 0, sizeof(TLBImplType
));
10954 TLBImplType_Constructor(impl_type
);
10955 impl_type
->hRef
= refType
;
10957 ++This
->typeattr
.cImplTypes
;
10959 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10960 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10962 hres
= ICreateTypeInfo2_LayOut(iface
);
10969 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10970 UINT index
, INT implTypeFlags
)
10972 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10973 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10975 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10977 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10978 return TYPE_E_BADMODULEKIND
;
10980 if (index
>= This
->typeattr
.cImplTypes
)
10981 return TYPE_E_ELEMENTNOTFOUND
;
10983 impl_type
->implflags
= implTypeFlags
;
10988 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10991 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10993 TRACE("%p %d\n", This
, alignment
);
10995 This
->typeattr
.cbAlignment
= alignment
;
11000 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
11003 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11005 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
11008 return E_INVALIDARG
;
11010 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
11012 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
11017 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
11018 UINT index
, VARDESC
*varDesc
)
11020 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11021 TLBVarDesc
*var_desc
;
11023 TRACE("%p %u %p\n", This
, index
, varDesc
);
11025 if (This
->vardescs
){
11028 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
11029 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
11031 if (index
< This
->typeattr
.cVars
) {
11032 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
11033 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
11034 var_desc
= This
->vardescs
+ index
;
11036 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
11038 /* move custdata lists to the new memory location */
11039 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
11041 TLB_relink_custdata(&This
->vardescs
[i
].custdata_list
);
11044 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
11046 TLBVarDesc_Constructor(var_desc
);
11047 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
11048 var_desc
->vardesc
= *var_desc
->vardesc_create
;
11050 ++This
->typeattr
.cVars
;
11052 This
->needs_layout
= TRUE
;
11057 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
11058 UINT index
, LPOLESTR
*names
, UINT numNames
)
11060 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11061 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11064 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
11067 return E_INVALIDARG
;
11069 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
11070 return TYPE_E_ELEMENTNOTFOUND
;
11072 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
11073 if(numNames
> func_desc
->funcdesc
.cParams
)
11074 return TYPE_E_ELEMENTNOTFOUND
;
11076 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
11077 return TYPE_E_ELEMENTNOTFOUND
;
11079 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
11080 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
11081 if (iter
->Name
&& !wcscmp(TLB_get_bstr(iter
->Name
), *names
)) {
11082 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
11083 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
11084 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
11086 return TYPE_E_AMBIGUOUSNAME
;
11090 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
11092 for (i
= 1; i
< numNames
; ++i
) {
11093 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
11094 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
11100 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
11101 UINT index
, LPOLESTR name
)
11103 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11105 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
11108 return E_INVALIDARG
;
11110 if(index
>= This
->typeattr
.cVars
)
11111 return TYPE_E_ELEMENTNOTFOUND
;
11113 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11117 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
11118 TYPEDESC
*tdescAlias
)
11120 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11123 TRACE("%p %p\n", This
, tdescAlias
);
11126 return E_INVALIDARG
;
11128 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
11129 return TYPE_E_BADMODULEKIND
;
11131 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
11135 heap_free(This
->tdescAlias
);
11136 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
11137 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
11142 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
11143 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
11145 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11146 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
11150 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
11151 UINT index
, LPOLESTR docString
)
11153 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11154 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11156 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11159 return E_INVALIDARG
;
11161 if(index
>= This
->typeattr
.cFuncs
)
11162 return TYPE_E_ELEMENTNOTFOUND
;
11164 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11169 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
11170 UINT index
, LPOLESTR docString
)
11172 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11173 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11175 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11178 return E_INVALIDARG
;
11180 if(index
>= This
->typeattr
.cVars
)
11181 return TYPE_E_ELEMENTNOTFOUND
;
11183 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11188 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
11189 UINT index
, DWORD helpContext
)
11191 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11192 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11194 TRACE("%p %u %d\n", This
, index
, helpContext
);
11196 if(index
>= This
->typeattr
.cFuncs
)
11197 return TYPE_E_ELEMENTNOTFOUND
;
11199 func_desc
->helpcontext
= helpContext
;
11204 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
11205 UINT index
, DWORD helpContext
)
11207 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11208 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11210 TRACE("%p %u %d\n", This
, index
, helpContext
);
11212 if(index
>= This
->typeattr
.cVars
)
11213 return TYPE_E_ELEMENTNOTFOUND
;
11215 var_desc
->HelpContext
= helpContext
;
11220 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
11221 UINT index
, BSTR bstrMops
)
11223 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11224 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
11228 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
11231 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11233 TRACE("%p %p\n", This
, idlDesc
);
11236 return E_INVALIDARG
;
11238 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11239 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11244 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11246 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11247 ITypeInfo2
*tinfo
= &This
->ITypeInfo2_iface
;
11248 TLBFuncDesc
*func_desc
;
11249 UINT user_vft
= 0, i
, depth
= 0;
11250 HRESULT hres
= S_OK
;
11252 TRACE("%p\n", This
);
11254 This
->needs_layout
= FALSE
;
11256 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11261 hres
= ITypeInfo2_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11263 if (SUCCEEDED(hres
)) {
11264 hres
= ITypeInfo2_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11266 if (SUCCEEDED(hres
)) {
11267 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11268 if (FAILED(hres
)) {
11269 ITypeInfo_Release(inh
);
11272 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11273 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11277 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11278 if(SUCCEEDED(hres
)){
11280 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11281 if(SUCCEEDED(hres
)){
11282 ITypeInfo_Release(inh
);
11286 }while(SUCCEEDED(hres
));
11289 ITypeInfo_Release(inh
);
11290 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11291 This
->typeattr
.cbSizeVft
= 0;
11295 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11296 This
->typeattr
.cbSizeVft
= 0;
11300 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11301 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11303 This
->typeattr
.cbSizeVft
= 0;
11305 func_desc
= This
->funcdescs
;
11307 while (i
< This
->typeattr
.cFuncs
) {
11308 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11309 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11311 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11312 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11314 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11316 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11319 BOOL reset
= FALSE
;
11321 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11323 iter
= This
->funcdescs
;
11324 while (j
< This
->typeattr
.cFuncs
) {
11325 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11327 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11330 ++func_desc
->funcdesc
.memid
;
11331 iter
= This
->funcdescs
;
11344 if (user_vft
> This
->typeattr
.cbSizeVft
)
11345 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11347 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11348 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11349 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11351 BOOL reset
= FALSE
;
11354 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11356 iter
= This
->vardescs
;
11357 while (j
< This
->typeattr
.cVars
) {
11358 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11360 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11363 ++var_desc
->vardesc
.memid
;
11364 iter
= This
->vardescs
;
11377 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11380 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11383 TRACE("%p %u\n", This
, index
);
11385 if (index
>= This
->typeattr
.cFuncs
)
11386 return TYPE_E_ELEMENTNOTFOUND
;
11388 typeinfo_release_funcdesc(&This
->funcdescs
[index
]);
11390 --This
->typeattr
.cFuncs
;
11391 if (index
!= This
->typeattr
.cFuncs
)
11393 memmove(This
->funcdescs
+ index
, This
->funcdescs
+ index
+ 1,
11394 sizeof(*This
->funcdescs
) * (This
->typeattr
.cFuncs
- index
));
11395 for (i
= index
; i
< This
->typeattr
.cFuncs
; ++i
)
11396 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
11399 This
->needs_layout
= TRUE
;
11404 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11405 MEMBERID memid
, INVOKEKIND invKind
)
11407 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11408 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11412 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11415 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11416 FIXME("%p %u - stub\n", This
, index
);
11420 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11423 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11424 FIXME("%p %x - stub\n", This
, memid
);
11428 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11431 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11434 TRACE("%p %u\n", This
, index
);
11436 if (index
>= This
->typeattr
.cImplTypes
)
11437 return TYPE_E_ELEMENTNOTFOUND
;
11439 TLB_FreeCustData(&This
->impltypes
[index
].custdata_list
);
11440 --This
->typeattr
.cImplTypes
;
11442 if (index
< This
->typeattr
.cImplTypes
)
11444 memmove(This
->impltypes
+ index
, This
->impltypes
+ index
+ 1, (This
->typeattr
.cImplTypes
- index
) *
11445 sizeof(*This
->impltypes
));
11446 for (i
= index
; i
< This
->typeattr
.cImplTypes
; ++i
)
11447 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
11453 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11454 REFGUID guid
, VARIANT
*varVal
)
11458 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11460 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11462 if (!guid
|| !varVal
)
11463 return E_INVALIDARG
;
11465 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11467 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11470 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11471 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11473 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11474 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11478 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11479 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11481 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11482 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11486 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11487 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11489 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11490 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11494 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11495 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11497 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11498 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11502 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11503 ULONG helpStringContext
)
11505 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11507 TRACE("%p %u\n", This
, helpStringContext
);
11509 This
->dwHelpStringContext
= helpStringContext
;
11514 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11515 UINT index
, ULONG helpStringContext
)
11517 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11518 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11522 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11523 UINT index
, ULONG helpStringContext
)
11525 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11526 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11530 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11532 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11533 FIXME("%p - stub\n", This
);
11537 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11540 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11542 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11545 return E_INVALIDARG
;
11547 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11552 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11553 ICreateTypeInfo2_fnQueryInterface
,
11554 ICreateTypeInfo2_fnAddRef
,
11555 ICreateTypeInfo2_fnRelease
,
11556 ICreateTypeInfo2_fnSetGuid
,
11557 ICreateTypeInfo2_fnSetTypeFlags
,
11558 ICreateTypeInfo2_fnSetDocString
,
11559 ICreateTypeInfo2_fnSetHelpContext
,
11560 ICreateTypeInfo2_fnSetVersion
,
11561 ICreateTypeInfo2_fnAddRefTypeInfo
,
11562 ICreateTypeInfo2_fnAddFuncDesc
,
11563 ICreateTypeInfo2_fnAddImplType
,
11564 ICreateTypeInfo2_fnSetImplTypeFlags
,
11565 ICreateTypeInfo2_fnSetAlignment
,
11566 ICreateTypeInfo2_fnSetSchema
,
11567 ICreateTypeInfo2_fnAddVarDesc
,
11568 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11569 ICreateTypeInfo2_fnSetVarName
,
11570 ICreateTypeInfo2_fnSetTypeDescAlias
,
11571 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11572 ICreateTypeInfo2_fnSetFuncDocString
,
11573 ICreateTypeInfo2_fnSetVarDocString
,
11574 ICreateTypeInfo2_fnSetFuncHelpContext
,
11575 ICreateTypeInfo2_fnSetVarHelpContext
,
11576 ICreateTypeInfo2_fnSetMops
,
11577 ICreateTypeInfo2_fnSetTypeIdldesc
,
11578 ICreateTypeInfo2_fnLayOut
,
11579 ICreateTypeInfo2_fnDeleteFuncDesc
,
11580 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11581 ICreateTypeInfo2_fnDeleteVarDesc
,
11582 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11583 ICreateTypeInfo2_fnDeleteImplType
,
11584 ICreateTypeInfo2_fnSetCustData
,
11585 ICreateTypeInfo2_fnSetFuncCustData
,
11586 ICreateTypeInfo2_fnSetParamCustData
,
11587 ICreateTypeInfo2_fnSetVarCustData
,
11588 ICreateTypeInfo2_fnSetImplTypeCustData
,
11589 ICreateTypeInfo2_fnSetHelpStringContext
,
11590 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11591 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11592 ICreateTypeInfo2_fnInvalidate
,
11593 ICreateTypeInfo2_fnSetName
11596 /******************************************************************************
11597 * ClearCustData (OLEAUT32.171)
11599 * Clear a custom data type's data.
11602 * lpCust [I] The custom data type instance
11607 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11609 if (lpCust
&& lpCust
->cCustData
)
11611 if (lpCust
->prgCustData
)
11615 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11616 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11618 CoTaskMemFree(lpCust
->prgCustData
);
11619 lpCust
->prgCustData
= NULL
;
11621 lpCust
->cCustData
= 0;