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 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7277 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7278 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7279 UINT vargs_converted
=0;
7284 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7286 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7288 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7289 hres
= DISP_E_PARAMNOTFOUND
;
7294 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7296 ERR("functions with the vararg attribute do not support named arguments\n");
7297 hres
= DISP_E_NONAMEDARGS
;
7301 for (i
= 0; i
< func_desc
->cParams
; i
++)
7303 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7304 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7309 TRACE("changing args\n");
7310 for (i
= 0; i
< func_desc
->cParams
; i
++)
7312 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7313 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7314 VARIANTARG
*src_arg
;
7316 if (wParamFlags
& PARAMFLAG_FLCID
)
7319 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7321 V_I4(arg
) = This
->pTypeLib
->lcid
;
7327 for (j
= 0; j
< cNamedArgs
; j
++)
7329 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7331 src_arg
= &pDispParams
->rgvarg
[j
];
7336 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7338 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7342 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7344 /* under most conditions the caller is not allowed to
7345 * pass in a dispparam arg in the index of what would be
7346 * the retval parameter. however, there is an exception
7347 * where the extra parameter is used in an extra
7348 * IDispatch::Invoke below */
7349 if ((i
< pDispParams
->cArgs
) &&
7350 ((func_desc
->cParams
!= 1) || !pVarResult
||
7351 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7353 hres
= DISP_E_BADPARAMCOUNT
;
7357 /* note: this check is placed so that if the caller passes
7358 * in a VARIANTARG for the retval we just ignore it, like
7360 if (i
== func_desc
->cParams
- 1)
7363 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7364 memset(arg
, 0, sizeof(*arg
));
7365 V_VT(arg
) = rgvt
[i
];
7366 memset(&retval
, 0, sizeof(retval
));
7367 V_BYREF(arg
) = &retval
;
7371 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7372 hres
= E_UNEXPECTED
;
7376 else if (src_arg
&& !((wParamFlags
& PARAMFLAG_FOPT
) &&
7377 V_VT(src_arg
) == VT_ERROR
&& V_ERROR(src_arg
) == DISP_E_PARAMNOTFOUND
))
7379 TRACE("%s\n", debugstr_variant(src_arg
));
7381 if(rgvt
[i
]!=V_VT(src_arg
))
7383 if (rgvt
[i
] == VT_VARIANT
)
7384 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7385 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7387 if (rgvt
[i
] == V_VT(src_arg
))
7388 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7391 if (wParamFlags
& PARAMFLAG_FIN
)
7392 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7393 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7395 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7397 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7399 SAFEARRAYBOUND bound
;
7403 bound
.cElements
= pDispParams
->cArgs
-i
;
7404 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7406 ERR("SafeArrayCreate failed\n");
7409 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7412 ERR("SafeArrayAccessData failed with %x\n", hres
);
7413 SafeArrayDestroy(a
);
7416 for (j
= 0; j
< bound
.cElements
; j
++)
7417 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7418 hres
= SafeArrayUnaccessData(a
);
7421 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7422 SafeArrayDestroy(a
);
7425 if (rgvt
[i
] & VT_BYREF
)
7426 V_BYREF(&rgvarg
[i
]) = &a
;
7428 V_ARRAY(&rgvarg
[i
]) = a
;
7429 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7431 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7433 if (wParamFlags
& PARAMFLAG_FIN
)
7434 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7436 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7437 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7438 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7440 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7442 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7443 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7447 /* FIXME: this doesn't work for VT_BYREF arguments if
7448 * they are not the same type as in the paramdesc */
7449 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7450 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7451 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7456 ERR("failed to convert param %d to %s from %s\n", i
,
7457 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7460 prgpvarg
[i
] = &rgvarg
[i
];
7464 prgpvarg
[i
] = src_arg
;
7467 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7468 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7469 && V_UNKNOWN(prgpvarg
[i
])) {
7470 IUnknown
*userdefined_iface
;
7473 if (tdesc
->vt
== VT_PTR
)
7474 tdesc
= tdesc
->u
.lptdesc
;
7476 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->u
.hreftype
, &guid
);
7480 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7482 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7486 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7487 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7490 else if (wParamFlags
& PARAMFLAG_FOPT
)
7493 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7494 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7496 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7502 /* if the function wants a pointer to a variant then
7503 * set that up, otherwise just pass the VT_ERROR in
7504 * the argument by value */
7505 if (rgvt
[i
] & VT_BYREF
)
7507 V_VT(&missing_arg
[i
]) = VT_ERROR
;
7508 V_ERROR(&missing_arg
[i
]) = DISP_E_PARAMNOTFOUND
;
7510 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7511 V_VARIANTREF(arg
) = &missing_arg
[i
];
7515 V_VT(arg
) = VT_ERROR
;
7516 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
7522 hres
= DISP_E_BADPARAMCOUNT
;
7526 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7528 /* VT_VOID is a special case for return types, so it is not
7529 * handled in the general function */
7530 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7531 V_VT(&varresult
) = VT_EMPTY
;
7534 V_VT(&varresult
) = 0;
7535 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7536 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7539 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7540 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7541 prgpvarg
, &varresult
);
7543 vargs_converted
= 0;
7545 for (i
= 0; i
< func_desc
->cParams
; i
++)
7547 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7549 if (wParamFlags
& PARAMFLAG_FLCID
)
7551 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7553 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7557 VariantInit(pVarResult
);
7558 /* deref return value */
7559 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7562 VARIANT_ClearInd(prgpvarg
[i
]);
7564 else if (vargs_converted
< pDispParams
->cArgs
)
7566 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7567 if (wParamFlags
& PARAMFLAG_FOUT
)
7569 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7571 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7575 ERR("failed to convert param %d to vt %d\n", i
,
7576 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7581 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7582 func_desc
->cParamsOpt
< 0 &&
7583 i
== func_desc
->cParams
-1)
7585 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7588 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7591 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7594 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7597 ERR("SafeArrayAccessData failed with %x\n", hres
);
7600 for (j
= 0; j
<= ubound
; j
++)
7601 VariantClear(&v
[j
]);
7602 hres
= SafeArrayUnaccessData(a
);
7605 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7609 VariantClear(&rgvarg
[i
]);
7612 else if (wParamFlags
& PARAMFLAG_FOPT
)
7614 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7615 VariantClear(&rgvarg
[i
]);
7618 VariantClear(&missing_arg
[i
]);
7621 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7623 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7624 hres
= DISP_E_EXCEPTION
;
7627 IErrorInfo
*pErrorInfo
;
7628 pExcepInfo
->scode
= V_ERROR(&varresult
);
7629 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7631 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7632 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7633 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7634 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7636 IErrorInfo_Release(pErrorInfo
);
7640 if (V_VT(&varresult
) != VT_ERROR
)
7642 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7646 VariantClear(pVarResult
);
7647 *pVarResult
= varresult
;
7650 VariantClear(&varresult
);
7653 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7654 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7655 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7656 (pDispParams
->cArgs
!= 0))
7658 if (V_VT(pVarResult
) == VT_DISPATCH
)
7660 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7661 /* Note: not VariantClear; we still need the dispatch
7662 * pointer to be valid */
7663 VariantInit(pVarResult
);
7664 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7665 GetSystemDefaultLCID(), wFlags
,
7666 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7667 IDispatch_Release(pDispatch
);
7671 VariantClear(pVarResult
);
7672 hres
= DISP_E_NOTACOLLECTION
;
7680 case FUNC_DISPATCH
: {
7683 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7684 if (SUCCEEDED(hres
)) {
7685 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7686 hres
= IDispatch_Invoke(
7687 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7688 pVarResult
,pExcepInfo
,pArgErr
7691 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7692 IDispatch_Release(disp
);
7694 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7698 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7703 TRACE("-- 0x%08x\n", hres
);
7706 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7709 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7710 if(FAILED(hres
)) return hres
;
7712 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7713 dump_VARDESC(var_desc
);
7714 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7718 /* not found, look for it in inherited interfaces */
7719 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7720 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7721 if(This
->impltypes
) {
7722 /* recursive search */
7724 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7725 if(SUCCEEDED(hres
)){
7726 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7727 ITypeInfo_Release(pTInfo
);
7730 WARN("Could not search inherited interface!\n");
7733 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7734 return DISP_E_MEMBERNOTFOUND
;
7737 /* ITypeInfo::GetDocumentation
7739 * Retrieves the documentation string, the complete Help file name and path,
7740 * and the context ID for the Help topic for a specified type description.
7742 * (Can be tested by the Visual Basic Editor in Word for instance.)
7744 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7745 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7746 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7748 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7749 const TLBFuncDesc
*pFDesc
;
7750 const TLBVarDesc
*pVDesc
;
7751 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7752 " HelpContext(%p) HelpFile(%p)\n",
7753 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7754 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7756 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7758 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7760 *pdwHelpContext
=This
->dwHelpContext
;
7762 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7764 }else {/* for a member */
7765 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
7768 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7770 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7772 *pdwHelpContext
=pFDesc
->helpcontext
;
7774 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7777 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
7780 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7782 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7784 *pdwHelpContext
=pVDesc
->HelpContext
;
7786 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7791 if(This
->impltypes
&&
7792 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7793 /* recursive search */
7796 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7797 if(SUCCEEDED(result
)) {
7798 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7799 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7800 ITypeInfo_Release(pTInfo
);
7803 WARN("Could not search inherited interface!\n");
7806 WARN("member %d not found\n", memid
);
7807 return TYPE_E_ELEMENTNOTFOUND
;
7810 /* ITypeInfo::GetDllEntry
7812 * Retrieves a description or specification of an entry point for a function
7815 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7816 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7819 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7820 const TLBFuncDesc
*pFDesc
;
7822 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7824 if (pBstrDllName
) *pBstrDllName
= NULL
;
7825 if (pBstrName
) *pBstrName
= NULL
;
7826 if (pwOrdinal
) *pwOrdinal
= 0;
7828 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7829 return TYPE_E_BADMODULEKIND
;
7831 pFDesc
= TLB_get_funcdesc_by_memberid_invkind(This
, memid
, invKind
);
7832 if (!pFDesc
) return TYPE_E_ELEMENTNOTFOUND
;
7834 dump_TypeInfo(This
);
7835 if (TRACE_ON(ole
)) dump_TLBFuncDescOne(pFDesc
);
7837 if (pBstrDllName
) *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7839 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1))
7841 if (pBstrName
) *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7842 if (pwOrdinal
) *pwOrdinal
= -1;
7846 if (pBstrName
) *pBstrName
= NULL
;
7847 if (pwOrdinal
) *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7852 /* internal function to make the inherited interfaces' methods appear
7853 * part of the interface */
7854 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7855 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7857 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7860 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7862 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7864 ITypeInfo
*pSubTypeInfo
;
7866 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7870 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7872 ITypeInfo_Release(pSubTypeInfo
);
7876 *hRefType
-= DISPATCH_HREF_OFFSET
;
7878 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7879 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7884 struct search_res_tlb_params
7890 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7892 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7893 WCHAR szPath
[MAX_PATH
+1];
7894 ITypeLib
*pTLib
= NULL
;
7898 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7901 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7904 if (swprintf(szPath
+ len
, ARRAY_SIZE(szPath
) - len
, L
"\\%d", LOWORD(lpszName
)) < 0)
7907 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7910 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7911 if (IsEqualGUID(params
->guid
, impl
->guid
))
7913 params
->pTLib
= pTLib
;
7914 return FALSE
; /* stop enumeration */
7916 ITypeLib_Release(pTLib
);
7922 /* ITypeInfo::GetRefTypeInfo
7924 * If a type description references other type descriptions, it retrieves
7925 * the referenced type descriptions.
7927 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7930 ITypeInfo
**ppTInfo
)
7932 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7933 ITypeInfo
*type_info
= NULL
;
7934 HRESULT result
= E_FAIL
;
7935 TLBRefType
*ref_type
;
7939 return E_INVALIDARG
;
7941 if ((INT
)hRefType
< 0) {
7942 ITypeInfoImpl
*pTypeInfoImpl
;
7944 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7945 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7946 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7947 return TYPE_E_ELEMENTNOTFOUND
;
7949 /* when we meet a DUAL typeinfo, we must create the alternate
7952 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7954 *pTypeInfoImpl
= *This
;
7955 pTypeInfoImpl
->ref
= 0;
7956 list_init(&pTypeInfoImpl
->custdata_list
);
7958 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7959 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7961 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7963 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7964 /* the AddRef implicitly adds a reference to the parent typelib, which
7965 * stops the copied data from being destroyed until the new typeinfo's
7966 * refcount goes to zero, but we need to signal to the new instance to
7967 * not free its data structures when it is destroyed */
7968 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7969 ITypeInfo_AddRef(*ppTInfo
);
7971 TRACE("got dual interface %p\n", *ppTInfo
);
7975 if ((hRefType
& DISPATCH_HREF_MASK
) && (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7976 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &hRefType
, ppTInfo
);
7978 if(!(hRefType
& 0x1))
7980 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7982 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7985 type_info
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7986 ITypeInfo_AddRef(type_info
);
7994 ITypeLib
*pTLib
= NULL
;
7996 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7998 if(ref_type
->reference
== (hRefType
& (~0x3)))
8001 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
8003 FIXME("Can't find pRefType for ref %x\n", hRefType
);
8007 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
8009 TRACE("internal reference\n");
8010 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
8012 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
8013 TRACE("typeinfo in imported typelib that is already loaded\n");
8014 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
8015 ITypeLib_AddRef(pTLib
);
8018 /* Search in cached typelibs */
8019 ITypeLibImpl
*entry
;
8021 EnterCriticalSection(&cache_section
);
8022 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
8025 && IsEqualIID(&entry
->guid
->guid
, TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
))
8026 && entry
->ver_major
== ref_type
->pImpTLInfo
->wVersionMajor
8027 && entry
->ver_minor
== ref_type
->pImpTLInfo
->wVersionMinor
8028 && entry
->set_lcid
== ref_type
->pImpTLInfo
->lcid
)
8030 TRACE("got cached %p\n", entry
);
8031 pTLib
= (ITypeLib
*)&entry
->ITypeLib2_iface
;
8032 ITypeLib_AddRef(pTLib
);
8037 LeaveCriticalSection(&cache_section
);
8041 struct search_res_tlb_params params
;
8043 TRACE("typeinfo in imported typelib that isn't already loaded\n");
8045 /* Search in resource table */
8046 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
8047 params
.pTLib
= NULL
;
8048 EnumResourceNamesW(NULL
, L
"TYPELIB", search_res_tlb
, (LONG_PTR
)¶ms
);
8051 pTLib
= params
.pTLib
;
8060 /* Search on disk */
8061 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
8062 ref_type
->pImpTLInfo
->wVersionMajor
,
8063 ref_type
->pImpTLInfo
->wVersionMinor
,
8064 This
->pTypeLib
->syskind
,
8065 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
8067 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
8069 result
= LoadTypeLib(libnam
, &pTLib
);
8070 SysFreeString(libnam
);
8073 if(SUCCEEDED(result
)) {
8074 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
8075 ITypeLib_AddRef(pTLib
);
8079 if(SUCCEEDED(result
)) {
8080 if(ref_type
->index
== TLB_REF_USE_GUID
)
8081 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), &type_info
);
8083 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, &type_info
);
8086 ITypeLib_Release(pTLib
);
8089 WARN("(%p) failed hreftype 0x%04x\n", This
, hRefType
);
8094 if ((hRefType
& 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info
, -2, ppTInfo
)))
8095 ITypeInfo_Release(type_info
);
8096 else *ppTInfo
= type_info
;
8098 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
8099 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
8103 /* ITypeInfo::AddressOfMember
8105 * Retrieves the addresses of static functions or variables, such as those
8108 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
8109 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
8111 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8117 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
8119 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
8123 module
= LoadLibraryW(dll
);
8126 ERR("couldn't load %s\n", debugstr_w(dll
));
8128 SysFreeString(entry
);
8129 return STG_E_FILENOTFOUND
;
8131 /* FIXME: store library somewhere where we can free it */
8136 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
8137 entryA
= heap_alloc(len
);
8138 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
8140 *ppv
= GetProcAddress(module
, entryA
);
8142 ERR("function not found %s\n", debugstr_a(entryA
));
8148 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
8150 ERR("function not found %d\n", ordinal
);
8154 SysFreeString(entry
);
8157 return TYPE_E_DLLFUNCTIONNOTFOUND
;
8162 /* ITypeInfo::CreateInstance
8164 * Creates a new instance of a type that describes a component object class
8167 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
8168 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
8170 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8174 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
8180 WARN("Not able to aggregate\n");
8181 return CLASS_E_NOAGGREGATION
;
8184 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
8185 if(FAILED(hr
)) return hr
;
8187 if(pTA
->typekind
!= TKIND_COCLASS
)
8189 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
8195 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
8198 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
8199 TRACE("GetActiveObject rets %08x\n", hr
);
8202 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
8203 IUnknown_Release(pUnk
);
8208 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
8209 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8213 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8217 /* ITypeInfo::GetMops
8219 * Retrieves marshalling information.
8221 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
8224 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8225 FIXME("(%p %d) stub!\n", This
, memid
);
8230 /* ITypeInfo::GetContainingTypeLib
8232 * Retrieves the containing type library and the index of the type description
8233 * within that type library.
8235 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8236 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8238 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8240 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8242 *pIndex
=This
->index
;
8243 TRACE("returning pIndex=%d\n", *pIndex
);
8247 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8248 ITypeLib_AddRef(*ppTLib
);
8249 TRACE("returning ppTLib=%p\n", *ppTLib
);
8255 /* ITypeInfo::ReleaseTypeAttr
8257 * Releases a TYPEATTR previously returned by Get
8260 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8261 TYPEATTR
* pTypeAttr
)
8263 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8264 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8265 heap_free(pTypeAttr
);
8268 /* ITypeInfo::ReleaseFuncDesc
8270 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8272 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8274 FUNCDESC
*pFuncDesc
)
8276 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8279 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8281 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8282 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8283 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8285 SysFreeString((BSTR
)pFuncDesc
);
8288 /* ITypeInfo::ReleaseVarDesc
8290 * Releases a VARDESC previously returned by GetVarDesc.
8292 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8295 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8296 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8298 TLB_FreeVarDesc(pVarDesc
);
8301 /* ITypeInfo2::GetTypeKind
8303 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8306 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8307 TYPEKIND
*pTypeKind
)
8309 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8310 *pTypeKind
= This
->typeattr
.typekind
;
8311 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8315 /* ITypeInfo2::GetTypeFlags
8317 * Returns the type flags without any allocations. This returns a DWORD type
8318 * flag, which expands the type flags without growing the TYPEATTR (type
8322 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8324 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8325 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8326 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
8330 /* ITypeInfo2::GetFuncIndexOfMemId
8331 * Binds to a specific member based on a known DISPID, where the member name
8332 * is not known (for example, when binding to a default member).
8335 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8336 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8338 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8342 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8343 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8344 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8347 if(fdc
< This
->typeattr
.cFuncs
) {
8351 result
= TYPE_E_ELEMENTNOTFOUND
;
8353 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
8354 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8358 /* TypeInfo2::GetVarIndexOfMemId
8360 * Binds to a specific member based on a known DISPID, where the member name
8361 * is not known (for example, when binding to a default member).
8364 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8365 MEMBERID memid
, UINT
*pVarIndex
)
8367 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8368 TLBVarDesc
*pVarInfo
;
8370 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8372 pVarInfo
= TLB_get_vardesc_by_memberid(This
, memid
);
8374 return TYPE_E_ELEMENTNOTFOUND
;
8376 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8381 /* ITypeInfo2::GetCustData
8383 * Gets the custom data
8385 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8390 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8391 TLBCustData
*pCData
;
8393 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8395 if(!guid
|| !pVarVal
)
8396 return E_INVALIDARG
;
8398 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8400 VariantInit( pVarVal
);
8402 VariantCopy( pVarVal
, &pCData
->data
);
8404 VariantClear( pVarVal
);
8408 /* ITypeInfo2::GetFuncCustData
8410 * Gets the custom data
8412 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8418 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8419 const TLBFuncDesc
*desc
;
8424 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8426 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &desc
, &hrefoffset
);
8429 WARN("description for function %d not found\n", index
);
8433 VariantInit(pVarVal
);
8434 data
= TLB_get_custdata_by_guid(&desc
->custdata_list
, guid
);
8435 return data
? VariantCopy(pVarVal
, &data
->data
) : S_OK
;
8438 /* ITypeInfo2::GetParamCustData
8440 * Gets the custom data
8442 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8449 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8450 const TLBFuncDesc
*pFDesc
;
8451 TLBCustData
*pCData
;
8455 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8456 debugstr_guid(guid
), pVarVal
);
8458 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8462 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8463 return TYPE_E_ELEMENTNOTFOUND
;
8465 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8467 return TYPE_E_ELEMENTNOTFOUND
;
8469 VariantInit(pVarVal
);
8470 VariantCopy(pVarVal
, &pCData
->data
);
8475 /* ITypeInfo2::GetVarCustData
8477 * Gets the custom data
8479 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8485 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8486 TLBCustData
*pCData
;
8487 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8489 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8491 if(index
>= This
->typeattr
.cVars
)
8492 return TYPE_E_ELEMENTNOTFOUND
;
8494 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8496 return TYPE_E_ELEMENTNOTFOUND
;
8498 VariantInit(pVarVal
);
8499 VariantCopy(pVarVal
, &pCData
->data
);
8504 /* ITypeInfo2::GetImplCustData
8506 * Gets the custom data
8508 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8514 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8515 TLBCustData
*pCData
;
8516 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8518 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8520 if(index
>= This
->typeattr
.cImplTypes
)
8521 return TYPE_E_ELEMENTNOTFOUND
;
8523 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8525 return TYPE_E_ELEMENTNOTFOUND
;
8527 VariantInit(pVarVal
);
8528 VariantCopy(pVarVal
, &pCData
->data
);
8533 /* ITypeInfo2::GetDocumentation2
8535 * Retrieves the documentation string, the complete Help file name and path,
8536 * the localization context to use, and the context ID for the library Help
8537 * topic in the Help file.
8540 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8544 BSTR
*pbstrHelpString
,
8545 DWORD
*pdwHelpStringContext
,
8546 BSTR
*pbstrHelpStringDll
)
8548 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8549 const TLBFuncDesc
*pFDesc
;
8550 const TLBVarDesc
*pVDesc
;
8551 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8552 "HelpStringContext(%p) HelpStringDll(%p)\n",
8553 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8554 pbstrHelpStringDll
);
8555 /* the help string should be obtained from the helpstringdll,
8556 * using the _DLLGetDocumentation function, based on the supplied
8557 * lcid. Nice to do sometime...
8559 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8561 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8562 if(pdwHelpStringContext
)
8563 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8564 if(pbstrHelpStringDll
)
8565 *pbstrHelpStringDll
=
8566 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8568 }else {/* for a member */
8569 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
8572 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8573 if(pdwHelpStringContext
)
8574 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8575 if(pbstrHelpStringDll
)
8576 *pbstrHelpStringDll
=
8577 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8580 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
8583 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8584 if(pdwHelpStringContext
)
8585 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8586 if(pbstrHelpStringDll
)
8587 *pbstrHelpStringDll
=
8588 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8592 return TYPE_E_ELEMENTNOTFOUND
;
8595 /* ITypeInfo2::GetAllCustData
8597 * Gets all custom data items for the Type info.
8600 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8602 CUSTDATA
*pCustData
)
8604 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8606 TRACE("%p %p\n", This
, pCustData
);
8608 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8611 /* ITypeInfo2::GetAllFuncCustData
8613 * Gets all custom data items for the specified Function
8616 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8619 CUSTDATA
*pCustData
)
8621 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8622 const TLBFuncDesc
*pFDesc
;
8626 TRACE("%p %u %p\n", This
, index
, pCustData
);
8628 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &pFDesc
, &hrefoffset
);
8632 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8635 /* ITypeInfo2::GetAllParamCustData
8637 * Gets all custom data items for the Functions
8640 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8641 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8643 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8644 const TLBFuncDesc
*pFDesc
;
8648 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8650 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8654 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8655 return TYPE_E_ELEMENTNOTFOUND
;
8657 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8660 /* ITypeInfo2::GetAllVarCustData
8662 * Gets all custom data items for the specified Variable
8665 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8666 UINT index
, CUSTDATA
*pCustData
)
8668 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8669 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8671 TRACE("%p %u %p\n", This
, index
, pCustData
);
8673 if(index
>= This
->typeattr
.cVars
)
8674 return TYPE_E_ELEMENTNOTFOUND
;
8676 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8679 /* ITypeInfo2::GetAllImplCustData
8681 * Gets all custom data items for the specified implementation type
8684 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8687 CUSTDATA
*pCustData
)
8689 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8690 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8692 TRACE("%p %u %p\n", This
, index
, pCustData
);
8694 if(index
>= This
->typeattr
.cImplTypes
)
8695 return TYPE_E_ELEMENTNOTFOUND
;
8697 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8700 static const ITypeInfo2Vtbl tinfvt
=
8703 ITypeInfo_fnQueryInterface
,
8705 ITypeInfo_fnRelease
,
8707 ITypeInfo_fnGetTypeAttr
,
8708 ITypeInfo_fnGetTypeComp
,
8709 ITypeInfo_fnGetFuncDesc
,
8710 ITypeInfo_fnGetVarDesc
,
8711 ITypeInfo_fnGetNames
,
8712 ITypeInfo_fnGetRefTypeOfImplType
,
8713 ITypeInfo_fnGetImplTypeFlags
,
8714 ITypeInfo_fnGetIDsOfNames
,
8716 ITypeInfo_fnGetDocumentation
,
8717 ITypeInfo_fnGetDllEntry
,
8718 ITypeInfo_fnGetRefTypeInfo
,
8719 ITypeInfo_fnAddressOfMember
,
8720 ITypeInfo_fnCreateInstance
,
8721 ITypeInfo_fnGetMops
,
8722 ITypeInfo_fnGetContainingTypeLib
,
8723 ITypeInfo_fnReleaseTypeAttr
,
8724 ITypeInfo_fnReleaseFuncDesc
,
8725 ITypeInfo_fnReleaseVarDesc
,
8727 ITypeInfo2_fnGetTypeKind
,
8728 ITypeInfo2_fnGetTypeFlags
,
8729 ITypeInfo2_fnGetFuncIndexOfMemId
,
8730 ITypeInfo2_fnGetVarIndexOfMemId
,
8731 ITypeInfo2_fnGetCustData
,
8732 ITypeInfo2_fnGetFuncCustData
,
8733 ITypeInfo2_fnGetParamCustData
,
8734 ITypeInfo2_fnGetVarCustData
,
8735 ITypeInfo2_fnGetImplTypeCustData
,
8736 ITypeInfo2_fnGetDocumentation2
,
8737 ITypeInfo2_fnGetAllCustData
,
8738 ITypeInfo2_fnGetAllFuncCustData
,
8739 ITypeInfo2_fnGetAllParamCustData
,
8740 ITypeInfo2_fnGetAllVarCustData
,
8741 ITypeInfo2_fnGetAllImplTypeCustData
,
8744 /******************************************************************************
8745 * CreateDispTypeInfo [OLEAUT32.31]
8747 * Build type information for an object so it can be called through an
8748 * IDispatch interface.
8751 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8752 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8755 * This call allows an objects methods to be accessed through IDispatch, by
8756 * building an ITypeInfo object that IDispatch can use to call through.
8758 HRESULT WINAPI
CreateDispTypeInfo(
8759 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8760 LCID lcid
, /* [I] Locale Id */
8761 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8763 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8764 ITypeLibImpl
*pTypeLibImpl
;
8765 unsigned int param
, func
;
8766 TLBFuncDesc
*pFuncDesc
;
8770 pTypeLibImpl
= TypeLibImpl_Constructor();
8771 if (!pTypeLibImpl
) return E_FAIL
;
8773 pTypeLibImpl
->TypeInfoCount
= 2;
8774 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8776 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8777 pTIIface
->pTypeLib
= pTypeLibImpl
;
8778 pTIIface
->index
= 0;
8779 pTIIface
->Name
= NULL
;
8780 pTIIface
->dwHelpContext
= -1;
8781 pTIIface
->guid
= NULL
;
8782 pTIIface
->typeattr
.lcid
= lcid
;
8783 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8784 pTIIface
->typeattr
.wMajorVerNum
= 0;
8785 pTIIface
->typeattr
.wMinorVerNum
= 0;
8786 pTIIface
->typeattr
.cbAlignment
= 2;
8787 pTIIface
->typeattr
.cbSizeInstance
= -1;
8788 pTIIface
->typeattr
.cbSizeVft
= -1;
8789 pTIIface
->typeattr
.cFuncs
= 0;
8790 pTIIface
->typeattr
.cImplTypes
= 0;
8791 pTIIface
->typeattr
.cVars
= 0;
8792 pTIIface
->typeattr
.wTypeFlags
= 0;
8793 pTIIface
->hreftype
= 0;
8795 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8796 pFuncDesc
= pTIIface
->funcdescs
;
8797 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8798 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8799 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8800 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8801 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8802 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8803 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8804 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8805 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8806 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8807 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8808 pFuncDesc
->funcdesc
.cScodes
= 0;
8809 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8810 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8811 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8812 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8813 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8814 md
->cArgs
* sizeof(ELEMDESC
));
8815 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8816 for(param
= 0; param
< md
->cArgs
; param
++) {
8817 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8818 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8820 pFuncDesc
->helpcontext
= 0;
8821 pFuncDesc
->HelpStringContext
= 0;
8822 pFuncDesc
->HelpString
= NULL
;
8823 pFuncDesc
->Entry
= NULL
;
8824 list_init(&pFuncDesc
->custdata_list
);
8825 pTIIface
->typeattr
.cFuncs
++;
8829 dump_TypeInfo(pTIIface
);
8831 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8832 pTIClass
->pTypeLib
= pTypeLibImpl
;
8833 pTIClass
->index
= 1;
8834 pTIClass
->Name
= NULL
;
8835 pTIClass
->dwHelpContext
= -1;
8836 pTIClass
->guid
= NULL
;
8837 pTIClass
->typeattr
.lcid
= lcid
;
8838 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8839 pTIClass
->typeattr
.wMajorVerNum
= 0;
8840 pTIClass
->typeattr
.wMinorVerNum
= 0;
8841 pTIClass
->typeattr
.cbAlignment
= 2;
8842 pTIClass
->typeattr
.cbSizeInstance
= -1;
8843 pTIClass
->typeattr
.cbSizeVft
= -1;
8844 pTIClass
->typeattr
.cFuncs
= 0;
8845 pTIClass
->typeattr
.cImplTypes
= 1;
8846 pTIClass
->typeattr
.cVars
= 0;
8847 pTIClass
->typeattr
.wTypeFlags
= 0;
8848 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8850 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8852 ref
= heap_alloc_zero(sizeof(*ref
));
8853 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8854 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8856 dump_TypeInfo(pTIClass
);
8858 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8860 ITypeInfo_AddRef(*pptinfo
);
8861 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8867 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8869 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8871 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8874 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8876 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8878 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8881 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8883 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8885 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8888 static HRESULT WINAPI
ITypeComp_fnBind(
8893 ITypeInfo
** ppTInfo
,
8894 DESCKIND
* pDescKind
,
8897 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8898 const TLBFuncDesc
*pFDesc
;
8899 const TLBVarDesc
*pVDesc
;
8900 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8903 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8905 *pDescKind
= DESCKIND_NONE
;
8906 pBindPtr
->lpfuncdesc
= NULL
;
8909 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8910 pFDesc
= &This
->funcdescs
[fdc
];
8911 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8912 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8915 /* name found, but wrong flags */
8916 hr
= TYPE_E_TYPEMISMATCH
;
8920 if (fdc
< This
->typeattr
.cFuncs
)
8922 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8924 &pBindPtr
->lpfuncdesc
,
8925 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8928 *pDescKind
= DESCKIND_FUNCDESC
;
8929 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8930 ITypeInfo_AddRef(*ppTInfo
);
8933 pVDesc
= TLB_get_vardesc_by_name(This
, szName
);
8935 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8938 *pDescKind
= DESCKIND_VARDESC
;
8939 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8940 ITypeInfo_AddRef(*ppTInfo
);
8945 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8946 /* recursive search */
8950 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8953 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8954 ITypeInfo_Release(pTInfo
);
8958 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8959 ITypeComp_Release(pTComp
);
8960 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8961 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8963 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8964 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8965 SysFreeString((BSTR
)tmp
);
8969 WARN("Could not search inherited interface!\n");
8971 if (hr
== DISP_E_MEMBERNOTFOUND
)
8973 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8977 static HRESULT WINAPI
ITypeComp_fnBindType(
8981 ITypeInfo
** ppTInfo
,
8982 ITypeComp
** ppTComp
)
8984 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8986 /* strange behaviour (does nothing) but like the
8989 if (!ppTInfo
|| !ppTComp
)
8998 static const ITypeCompVtbl tcompvt
=
9001 ITypeComp_fnQueryInterface
,
9003 ITypeComp_fnRelease
,
9006 ITypeComp_fnBindType
9009 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
9010 ICreateTypeLib2
** ppctlib
)
9015 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
9017 if (!szFile
) return E_INVALIDARG
;
9019 This
= TypeLibImpl_Constructor();
9021 return E_OUTOFMEMORY
;
9023 This
->lcid
= GetSystemDefaultLCID();
9024 This
->syskind
= syskind
;
9025 This
->ptr_size
= get_ptr_size(syskind
);
9027 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
9029 ITypeLib2_Release(&This
->ITypeLib2_iface
);
9030 return E_OUTOFMEMORY
;
9032 lstrcpyW(This
->path
, szFile
);
9034 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
9035 ITypeLib2_Release(&This
->ITypeLib2_iface
);
9039 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
9040 REFIID riid
, void **object
)
9042 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9044 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
9047 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
9049 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9051 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
9054 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
9056 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9058 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
9061 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
9062 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
9064 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9065 ITypeInfoImpl
*info
;
9068 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
9070 if (!ctinfo
|| !name
)
9071 return E_INVALIDARG
;
9073 info
= TLB_get_typeinfo_by_name(This
, name
);
9075 return TYPE_E_NAMECONFLICT
;
9077 if (This
->typeinfos
)
9078 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
9079 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
9081 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
9083 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
9085 info
->pTypeLib
= This
;
9086 info
->Name
= TLB_append_str(&This
->name_list
, name
);
9087 info
->index
= This
->TypeInfoCount
;
9088 info
->typeattr
.typekind
= kind
;
9089 info
->typeattr
.cbAlignment
= 4;
9091 switch (info
->typeattr
.typekind
) {
9093 case TKIND_INTERFACE
:
9094 case TKIND_DISPATCH
:
9096 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
9100 info
->typeattr
.cbSizeInstance
= 0;
9103 info
->typeattr
.cbSizeInstance
= 2;
9106 info
->typeattr
.cbSizeInstance
= -0x75;
9109 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
9110 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
9114 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
9115 &IID_ICreateTypeInfo
, (void **)ctinfo
);
9117 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
9121 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
9123 ++This
->TypeInfoCount
;
9128 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
9131 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9133 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
9136 return E_INVALIDARG
;
9138 This
->Name
= TLB_append_str(&This
->name_list
, name
);
9143 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
9144 WORD majorVerNum
, WORD minorVerNum
)
9146 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9148 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
9150 This
->ver_major
= majorVerNum
;
9151 This
->ver_minor
= minorVerNum
;
9156 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
9159 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9161 TRACE("%p %s\n", This
, debugstr_guid(guid
));
9163 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
9168 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
9171 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9173 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
9176 return E_INVALIDARG
;
9178 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
9183 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
9184 LPOLESTR helpFileName
)
9186 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9188 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
9191 return E_INVALIDARG
;
9193 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
9198 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
9201 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9203 TRACE("%p %d\n", This
, helpContext
);
9205 This
->dwHelpContext
= helpContext
;
9210 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
9213 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9215 TRACE("%p %x\n", This
, lcid
);
9217 This
->set_lcid
= lcid
;
9222 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9225 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9227 TRACE("%p %x\n", This
, libFlags
);
9229 This
->libflags
= libFlags
;
9234 typedef struct tagWMSFT_SegContents
{
9237 } WMSFT_SegContents
;
9239 typedef struct tagWMSFT_TLBFile
{
9241 WMSFT_SegContents typeinfo_seg
;
9242 WMSFT_SegContents impfile_seg
;
9243 WMSFT_SegContents impinfo_seg
;
9244 WMSFT_SegContents ref_seg
;
9245 WMSFT_SegContents guidhash_seg
;
9246 WMSFT_SegContents guid_seg
;
9247 WMSFT_SegContents namehash_seg
;
9248 WMSFT_SegContents name_seg
;
9249 WMSFT_SegContents string_seg
;
9250 WMSFT_SegContents typdesc_seg
;
9251 WMSFT_SegContents arraydesc_seg
;
9252 WMSFT_SegContents custdata_seg
;
9253 WMSFT_SegContents cdguids_seg
;
9255 WMSFT_SegContents aux_seg
;
9258 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9259 WMSFT_TLBFile
*file
)
9265 file
->string_seg
.len
= 0;
9266 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9269 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9271 return E_UNEXPECTED
;
9273 size
+= sizeof(INT16
);
9275 size
= (size
+ 4) & ~0x3;
9279 file
->string_seg
.len
+= size
;
9281 /* temporarily use str->offset to store the length of the aligned,
9282 * converted string */
9286 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
9289 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9292 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9293 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9295 heap_free(file
->string_seg
.data
);
9296 return E_UNEXPECTED
;
9299 *((INT16
*)data
) = size
;
9301 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9305 str
->offset
= last_offs
;
9312 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9313 WMSFT_TLBFile
*file
)
9318 MSFT_NameIntro
*last_intro
= NULL
;
9320 file
->header
.nametablecount
= 0;
9321 file
->header
.nametablechars
= 0;
9323 file
->name_seg
.len
= 0;
9324 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9327 size
= lstrlenW(str
->str
);
9328 file
->header
.nametablechars
+= size
;
9329 file
->header
.nametablecount
++;
9331 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9333 return E_UNEXPECTED
;
9335 size
+= sizeof(MSFT_NameIntro
);
9337 size
= (size
+ 4) & ~0x3;
9341 file
->name_seg
.len
+= size
;
9343 /* temporarily use str->offset to store the length of the aligned,
9344 * converted string */
9348 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9349 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
9352 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9354 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9356 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9357 data
+ sizeof(MSFT_NameIntro
),
9358 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9360 heap_free(file
->name_seg
.data
);
9361 return E_UNEXPECTED
;
9363 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9365 intro
->hreftype
= -1; /* TODO? */
9366 intro
->namelen
= size
& 0xFF;
9367 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9368 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9369 intro
->namelen
|= hash
<< 16;
9370 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9371 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9373 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9374 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9376 /* update str->offset to actual value to use in other
9377 * compilation functions that require positions within
9378 * the string table */
9382 str
->offset
= last_offs
;
9387 last_intro
->hreftype
= 0; /* last one is 0? */
9392 static inline int hash_guid(GUID
*guid
)
9396 for (i
= 0; i
< 8; i
++)
9397 hash
^= ((const short *)guid
)[i
];
9402 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9405 MSFT_GuidEntry
*entry
;
9407 int hash_key
, *guidhashtab
;
9409 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9410 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9412 entry
= file
->guid_seg
.data
;
9414 guidhashtab
= file
->guidhash_seg
.data
;
9415 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9416 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9417 entry
->hreftype
= guid
->hreftype
;
9419 hash_key
= hash_guid(&guid
->guid
);
9420 entry
->next_hash
= guidhashtab
[hash_key
];
9421 guidhashtab
[hash_key
] = offs
;
9423 guid
->offset
= offs
;
9424 offs
+= sizeof(MSFT_GuidEntry
);
9431 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9434 VARTYPE arg_type
= V_VT(value
);
9437 DWORD ret
= file
->custdata_seg
.len
;
9439 if(arg_type
== VT_INT
)
9441 if(arg_type
== VT_UINT
)
9445 if(V_VT(value
) != arg_type
) {
9446 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9448 ERR("VariantChangeType failed: %08x\n", hres
);
9453 /* Check if default value can be stored in-place */
9458 if(V_UI4(&v
) > 0x3ffffff)
9471 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9474 /* have to allocate space in custdata_seg */
9483 /* Construct the data to be allocated */
9486 if(file
->custdata_seg
.data
){
9487 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9488 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9489 file
->custdata_seg
.len
+= sizeof(int) * 2;
9491 file
->custdata_seg
.len
= sizeof(int) * 2;
9492 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9495 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9496 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9498 /* TODO: Check if the encoded data is already present in custdata_seg */
9504 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9507 if(file
->custdata_seg
.data
){
9508 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9509 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9510 file
->custdata_seg
.len
+= len
;
9512 file
->custdata_seg
.len
= len
;
9513 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9516 *((unsigned short *)data
) = V_VT(value
);
9517 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9518 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9519 if(V_BSTR(&v
)[i
] <= 0x7f)
9520 data
[i
+6] = V_BSTR(&v
)[i
];
9524 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9525 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9528 /* TODO: Check if the encoded data is already present in custdata_seg */
9533 FIXME("Argument type not yet handled\n");
9538 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9540 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9542 DWORD offs
= file
->arraydesc_seg
.len
;
9546 /* TODO: we should check for duplicates, but that's harder because each
9547 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9548 * at the library-level) */
9550 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9551 if(!file
->arraydesc_seg
.data
)
9552 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9554 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9555 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9557 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9558 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9559 for(i
= 0; i
< desc
->cDims
; ++i
){
9560 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9561 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9567 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9573 VARTYPE vt
, subtype
;
9584 vt
= desc
->vt
& VT_TYPEMASK
;
9586 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9588 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9589 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9591 *out_size
+= 2 * sizeof(DWORD
);
9592 }else if(vt
== VT_CARRAY
){
9593 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9594 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9596 }else if(vt
== VT_USERDEFINED
){
9597 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9598 encoded
[1] = desc
->u
.hreftype
;
9599 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9601 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9619 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9622 data
= file
->typdesc_seg
.data
;
9623 while(offs
< file
->typdesc_seg
.len
){
9624 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9626 offs
+= sizeof(encoded
);
9629 file
->typdesc_seg
.len
+= sizeof(encoded
);
9630 if(!file
->typdesc_seg
.data
)
9631 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9633 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9635 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9640 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9642 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9643 DWORD ret
= cdguids_seg
->len
, offs
;
9644 MSFT_CDGuid
*cdguid
;
9647 if(list_empty(custdata_list
))
9650 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9651 if(!cdguids_seg
->data
){
9652 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9654 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9655 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9658 offs
= ret
+ sizeof(MSFT_CDGuid
);
9659 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9660 cdguid
->GuidOffset
= cd
->guid
->offset
;
9661 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9662 cdguid
->next
= offs
;
9663 offs
+= sizeof(MSFT_CDGuid
);
9673 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9674 WMSFT_TLBFile
*file
)
9676 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9677 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9678 MSFT_VarRecord
*varrecord
;
9679 MSFT_FuncRecord
*funcrecord
;
9681 DWORD
*name
, *offsets
, offs
;
9683 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9684 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9686 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9688 /* optional fields */
9689 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9690 if(!list_empty(&desc
->custdata_list
))
9691 recorded_size
+= 7 * sizeof(INT
);
9692 else if(desc
->HelpStringContext
!= 0)
9693 recorded_size
+= 6 * sizeof(INT
);
9695 else if(desc
->Entry
)
9696 recorded_size
+= 3 * sizeof(INT
);
9697 else if(desc
->HelpString
)
9698 recorded_size
+= 2 * sizeof(INT
);
9699 else if(desc
->helpcontext
)
9700 recorded_size
+= sizeof(INT
);
9702 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9704 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9705 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9706 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9711 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9714 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9715 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9717 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9719 /* optional fields */
9720 if(desc
->HelpStringContext
!= 0)
9721 recorded_size
+= 5 * sizeof(INT
);
9722 else if(!list_empty(&desc
->custdata_list
))
9723 recorded_size
+= 4 * sizeof(INT
);
9725 else if(desc
->HelpString
)
9726 recorded_size
+= 2 * sizeof(INT
);
9727 else if(desc
->HelpContext
!= 0)
9728 recorded_size
+= sizeof(INT
);
9730 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9733 if(!recorded_size
&& !extra_size
)
9736 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9738 aux_seg
->len
+= recorded_size
+ extra_size
;
9740 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9743 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9745 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9747 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9749 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9752 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9753 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9754 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9755 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9757 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9758 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9759 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9760 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9763 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9768 * ^has_param_defaults
9769 * ^oEntry_is_intresource
9771 funcrecord
->FKCCIC
=
9772 desc
->funcdesc
.funckind
|
9773 (desc
->funcdesc
.invkind
<< 3) |
9774 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9775 (desc
->funcdesc
.callconv
<< 8);
9777 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9778 funcrecord
->FKCCIC
|= 0x2000;
9780 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9781 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9782 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9783 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9786 if(paramdefault_size
> 0)
9787 funcrecord
->FKCCIC
|= 0x1000;
9789 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9790 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9792 /* optional fields */
9794 if(!list_empty(&desc
->custdata_list
)){
9795 size
+= 7 * sizeof(INT
);
9796 funcrecord
->HelpContext
= desc
->helpcontext
;
9797 if(desc
->HelpString
)
9798 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9800 funcrecord
->oHelpString
= -1;
9802 funcrecord
->oEntry
= -1;
9803 else if(IS_INTRESOURCE(desc
->Entry
))
9804 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9806 funcrecord
->oEntry
= desc
->Entry
->offset
;
9807 funcrecord
->res9
= -1;
9808 funcrecord
->resA
= -1;
9809 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9810 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9811 }else if(desc
->HelpStringContext
!= 0){
9812 size
+= 6 * sizeof(INT
);
9813 funcrecord
->HelpContext
= desc
->helpcontext
;
9814 if(desc
->HelpString
)
9815 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9817 funcrecord
->oHelpString
= -1;
9819 funcrecord
->oEntry
= -1;
9820 else if(IS_INTRESOURCE(desc
->Entry
))
9821 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9823 funcrecord
->oEntry
= desc
->Entry
->offset
;
9824 funcrecord
->res9
= -1;
9825 funcrecord
->resA
= -1;
9826 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9827 }else if(desc
->Entry
){
9828 size
+= 3 * sizeof(INT
);
9829 funcrecord
->HelpContext
= desc
->helpcontext
;
9830 if(desc
->HelpString
)
9831 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9833 funcrecord
->oHelpString
= -1;
9835 funcrecord
->oEntry
= -1;
9836 else if(IS_INTRESOURCE(desc
->Entry
))
9837 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9839 funcrecord
->oEntry
= desc
->Entry
->offset
;
9840 }else if(desc
->HelpString
){
9841 size
+= 2 * sizeof(INT
);
9842 funcrecord
->HelpContext
= desc
->helpcontext
;
9843 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9844 }else if(desc
->helpcontext
){
9845 size
+= sizeof(INT
);
9846 funcrecord
->HelpContext
= desc
->helpcontext
;
9849 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9850 size
+= paramdefault_size
;
9852 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9853 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9855 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9856 if(desc
->pParamDesc
[j
].Name
)
9857 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9860 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9862 if(paramdefault_size
){
9863 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9864 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9865 else if(paramdefault_size
)
9870 size
+= sizeof(MSFT_ParameterInfo
);
9873 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9879 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9882 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9883 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9884 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9885 DWORD size
= 5 * sizeof(INT
);
9887 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9888 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9889 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9890 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9892 if(desc
->vardesc
.varkind
== VAR_CONST
){
9893 varrecord
->vardescsize
+= sizeof(VARIANT
);
9894 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9896 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9899 if(desc
->HelpStringContext
!= 0){
9900 size
+= 5 * sizeof(INT
);
9901 varrecord
->HelpContext
= desc
->HelpContext
;
9902 if(desc
->HelpString
)
9903 varrecord
->HelpString
= desc
->HelpString
->offset
;
9905 varrecord
->HelpString
= -1;
9906 varrecord
->res9
= -1;
9907 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9908 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9909 }else if(!list_empty(&desc
->custdata_list
)){
9910 size
+= 4 * sizeof(INT
);
9911 varrecord
->HelpContext
= desc
->HelpContext
;
9912 if(desc
->HelpString
)
9913 varrecord
->HelpString
= desc
->HelpString
->offset
;
9915 varrecord
->HelpString
= -1;
9916 varrecord
->res9
= -1;
9917 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9918 }else if(desc
->HelpString
){
9919 size
+= 2 * sizeof(INT
);
9920 varrecord
->HelpContext
= desc
->HelpContext
;
9921 if(desc
->HelpString
)
9922 varrecord
->HelpString
= desc
->HelpString
->offset
;
9924 varrecord
->HelpString
= -1;
9925 }else if(desc
->HelpContext
!= 0){
9926 size
+= sizeof(INT
);
9927 varrecord
->HelpContext
= desc
->HelpContext
;
9930 varrecord
->Info
= size
| (i
<< 16);
9936 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9939 memid
= (MEMBERID
*)varrecord
;
9940 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9941 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9942 *memid
= desc
->funcdesc
.memid
;
9945 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9946 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9947 *memid
= desc
->vardesc
.memid
;
9951 name
= (UINT
*)memid
;
9952 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9953 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9955 *name
= desc
->Name
->offset
;
9960 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9961 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9963 *name
= desc
->Name
->offset
;
9972 typedef struct tagWMSFT_RefChunk
{
9979 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9981 DWORD offs
= file
->ref_seg
.len
, i
;
9982 WMSFT_RefChunk
*chunk
;
9984 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9985 if(!file
->ref_seg
.data
)
9986 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9988 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9990 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9992 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9993 chunk
->href
= info
->impltypes
[i
].hRef
;
9994 chunk
->res04
= info
->impltypes
[i
].implflags
;
9996 if(i
< info
->typeattr
.cImplTypes
- 1)
9997 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
10006 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
10010 size
= sizeof(MSFT_TypeInfoBase
);
10013 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
10014 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
10015 base
->typekind
= TKIND_DISPATCH
;
10017 base
->typekind
= info
->typeattr
.typekind
;
10018 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
10019 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
10020 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
10025 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
10031 base
->posguid
= info
->guid
->offset
;
10033 base
->posguid
= -1;
10034 base
->flags
= info
->typeattr
.wTypeFlags
;
10036 base
->NameOffset
= info
->Name
->offset
;
10038 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
10039 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
10041 base
->NameOffset
= -1;
10043 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
10044 if(info
->DocString
)
10045 base
->docstringoffs
= info
->DocString
->offset
;
10047 base
->docstringoffs
= -1;
10048 base
->helpstringcontext
= info
->dwHelpStringContext
;
10049 base
->helpcontext
= info
->dwHelpContext
;
10050 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
10051 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
10052 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
10053 base
->size
= info
->typeattr
.cbSizeInstance
;
10054 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
10055 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
10056 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
10057 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
10058 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
10060 base
->datatype1
= info
->DllName
->offset
;
10062 base
->datatype1
= -1;
10064 if(info
->typeattr
.cImplTypes
> 0)
10065 base
->datatype1
= info
->impltypes
[0].hRef
;
10067 base
->datatype1
= -1;
10069 base
->datatype2
= index
; /* FIXME: i think there's more here */
10077 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
10081 file
->typeinfo_seg
.len
= 0;
10082 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10083 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
10084 *junk
= file
->typeinfo_seg
.len
;
10086 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
10089 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
10090 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
10092 file
->aux_seg
.len
= 0;
10093 file
->aux_seg
.data
= NULL
;
10095 file
->typeinfo_seg
.len
= 0;
10096 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10097 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
10098 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
10099 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
10103 typedef struct tagWMSFT_ImpFile
{
10109 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10112 WMSFT_ImpFile
*impfile
;
10114 DWORD last_offs
= 0;
10116 file
->impfile_seg
.len
= 0;
10117 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10121 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10125 path
= implib
->name
;
10126 size
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
), NULL
, 0, NULL
, NULL
);
10128 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10131 size
+= sizeof(INT16
);
10133 size
= (size
+ 4) & ~0x3;
10137 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
10140 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
10142 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10143 int strlen
= 0, size
;
10145 impfile
= (WMSFT_ImpFile
*)data
;
10146 impfile
->guid_offs
= implib
->guid
->offset
;
10147 impfile
->lcid
= implib
->lcid
;
10148 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
10150 data
+= sizeof(WMSFT_ImpFile
);
10153 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10157 path
= implib
->name
;
10158 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
),
10159 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
10161 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10164 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
10166 size
= strlen
+ sizeof(INT16
);
10168 size
= (size
+ 4) & ~0x3;
10171 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
10174 implib
->offset
= last_offs
;
10175 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
10179 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10181 MSFT_ImpInfo
*info
;
10182 TLBRefType
*ref_type
;
10185 WMSFT_compile_impfile(This
, file
);
10187 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
10188 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
10190 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
10191 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
10192 if(ref_type
->index
== TLB_REF_USE_GUID
){
10193 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
10194 info
->oGuid
= ref_type
->guid
->offset
;
10196 info
->oGuid
= ref_type
->index
;
10197 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
10203 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10205 file
->guidhash_seg
.len
= 0x80;
10206 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
10207 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
10210 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10212 file
->namehash_seg
.len
= 0x200;
10213 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
10214 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
10217 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
10219 if(contents
&& contents
->len
){
10220 segdir
->offset
= *running_offset
;
10221 segdir
->length
= contents
->len
;
10222 *running_offset
+= segdir
->length
;
10224 segdir
->offset
= -1;
10225 segdir
->length
= 0;
10228 /* TODO: do these ever change? */
10229 segdir
->res08
= -1;
10230 segdir
->res0c
= 0xf;
10233 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10237 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10240 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10244 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10246 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10247 base
->memoffset
+= file_len
;
10254 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10256 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
10257 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
10258 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
10259 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
10260 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
10261 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
10262 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
10263 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
10264 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
10265 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
10266 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
10267 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
10268 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
10269 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
10272 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10274 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10275 WMSFT_TLBFile file
;
10276 DWORD written
, junk_size
, junk_offs
, running_offset
;
10283 TRACE("%p\n", This
);
10285 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10286 if(This
->typeinfos
[i
]->needs_layout
)
10287 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10289 memset(&file
, 0, sizeof(file
));
10291 file
.header
.magic1
= 0x5446534D;
10292 file
.header
.magic2
= 0x00010002;
10293 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10294 file
.header
.lcid2
= This
->set_lcid
;
10295 file
.header
.varflags
= 0x40 | This
->syskind
;
10296 if (This
->HelpFile
)
10297 file
.header
.varflags
|= 0x10;
10298 if (This
->HelpStringDll
)
10299 file
.header
.varflags
|= HELPDLLFLAG
;
10300 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10301 file
.header
.flags
= This
->libflags
;
10302 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10303 file
.header
.helpcontext
= This
->dwHelpContext
;
10304 file
.header
.res44
= 0x20;
10305 file
.header
.res48
= 0x80;
10306 file
.header
.dispatchpos
= This
->dispatch_href
;
10308 WMSFT_compile_namehash(This
, &file
);
10309 /* do name and string compilation to get offsets for other compilations */
10310 hres
= WMSFT_compile_names(This
, &file
);
10312 WMSFT_free_file(&file
);
10316 hres
= WMSFT_compile_strings(This
, &file
);
10318 WMSFT_free_file(&file
);
10322 WMSFT_compile_guidhash(This
, &file
);
10323 hres
= WMSFT_compile_guids(This
, &file
);
10325 WMSFT_free_file(&file
);
10330 file
.header
.helpfile
= This
->HelpFile
->offset
;
10332 file
.header
.helpfile
= -1;
10334 if(This
->DocString
)
10335 file
.header
.helpstring
= This
->DocString
->offset
;
10337 file
.header
.helpstring
= -1;
10339 /* do some more segment compilation */
10340 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10341 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10344 file
.header
.NameOffset
= This
->Name
->offset
;
10346 file
.header
.NameOffset
= -1;
10348 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10351 file
.header
.posguid
= This
->guid
->offset
;
10353 file
.header
.posguid
= -1;
10355 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10356 if(file
.header
.varflags
& HELPDLLFLAG
)
10357 junk_size
+= sizeof(DWORD
);
10359 junk
= heap_alloc_zero(junk_size
);
10360 if(file
.header
.varflags
& HELPDLLFLAG
){
10361 *junk
= This
->HelpStringDll
->offset
;
10370 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10371 WMSFT_compile_impinfo(This
, &file
);
10373 running_offset
= 0;
10375 TRACE("header at: 0x%x\n", running_offset
);
10376 running_offset
+= sizeof(file
.header
);
10378 TRACE("junk at: 0x%x\n", running_offset
);
10379 running_offset
+= junk_size
;
10381 TRACE("segdir at: 0x%x\n", running_offset
);
10382 running_offset
+= sizeof(file
.segdir
);
10384 TRACE("typeinfo at: 0x%x\n", running_offset
);
10385 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10387 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10388 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10390 TRACE("guidtab at: 0x%x\n", running_offset
);
10391 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10393 TRACE("reftab at: 0x%x\n", running_offset
);
10394 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10396 TRACE("impinfo at: 0x%x\n", running_offset
);
10397 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10399 TRACE("impfiles at: 0x%x\n", running_offset
);
10400 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10402 TRACE("namehashtab at: 0x%x\n", running_offset
);
10403 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10405 TRACE("nametab at: 0x%x\n", running_offset
);
10406 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10408 TRACE("stringtab at: 0x%x\n", running_offset
);
10409 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10411 TRACE("typdesc at: 0x%x\n", running_offset
);
10412 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10414 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10415 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10417 TRACE("custdata at: 0x%x\n", running_offset
);
10418 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10420 TRACE("cdguids at: 0x%x\n", running_offset
);
10421 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10423 TRACE("res0e at: 0x%x\n", running_offset
);
10424 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10426 TRACE("res0f at: 0x%x\n", running_offset
);
10427 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10429 TRACE("aux_seg at: 0x%x\n", running_offset
);
10431 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10433 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10434 FILE_ATTRIBUTE_NORMAL
, 0);
10435 if (outfile
== INVALID_HANDLE_VALUE
){
10436 WMSFT_free_file(&file
);
10438 return TYPE_E_IOERROR
;
10441 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10443 WMSFT_free_file(&file
);
10444 CloseHandle(outfile
);
10446 return TYPE_E_IOERROR
;
10449 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10452 WMSFT_free_file(&file
);
10453 CloseHandle(outfile
);
10454 return TYPE_E_IOERROR
;
10457 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10459 WMSFT_free_file(&file
);
10460 CloseHandle(outfile
);
10461 return TYPE_E_IOERROR
;
10464 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10465 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10466 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10467 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10468 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10469 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10470 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10471 WMSFT_write_segment(outfile
, &file
.name_seg
);
10472 WMSFT_write_segment(outfile
, &file
.string_seg
);
10473 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10474 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10475 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10476 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10477 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10479 WMSFT_free_file(&file
);
10481 CloseHandle(outfile
);
10486 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10489 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10490 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10494 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10495 REFGUID guid
, VARIANT
*varVal
)
10497 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10500 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10502 if (!guid
|| !varVal
)
10503 return E_INVALIDARG
;
10505 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10507 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10510 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10511 ULONG helpStringContext
)
10513 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10514 FIXME("%p %u - stub\n", This
, helpStringContext
);
10518 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10521 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10522 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10525 return E_INVALIDARG
;
10527 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10532 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10533 ICreateTypeLib2_fnQueryInterface
,
10534 ICreateTypeLib2_fnAddRef
,
10535 ICreateTypeLib2_fnRelease
,
10536 ICreateTypeLib2_fnCreateTypeInfo
,
10537 ICreateTypeLib2_fnSetName
,
10538 ICreateTypeLib2_fnSetVersion
,
10539 ICreateTypeLib2_fnSetGuid
,
10540 ICreateTypeLib2_fnSetDocString
,
10541 ICreateTypeLib2_fnSetHelpFileName
,
10542 ICreateTypeLib2_fnSetHelpContext
,
10543 ICreateTypeLib2_fnSetLcid
,
10544 ICreateTypeLib2_fnSetLibFlags
,
10545 ICreateTypeLib2_fnSaveAllChanges
,
10546 ICreateTypeLib2_fnDeleteTypeInfo
,
10547 ICreateTypeLib2_fnSetCustData
,
10548 ICreateTypeLib2_fnSetHelpStringContext
,
10549 ICreateTypeLib2_fnSetHelpStringDll
10552 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10553 REFIID riid
, void **object
)
10555 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10557 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10560 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10562 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10564 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10567 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10569 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10571 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10574 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10577 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10579 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10581 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10586 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10589 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10593 TRACE("%p %x\n", This
, typeFlags
);
10595 if (typeFlags
& TYPEFLAG_FDUAL
) {
10597 ITypeInfo
*dispatch
;
10601 hres
= LoadTypeLib(L
"stdole2.tlb", &stdole
);
10605 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10606 ITypeLib_Release(stdole
);
10610 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10611 ITypeInfo_Release(dispatch
);
10616 old_flags
= This
->typeattr
.wTypeFlags
;
10617 This
->typeattr
.wTypeFlags
= typeFlags
;
10619 hres
= ICreateTypeInfo2_LayOut(iface
);
10620 if (FAILED(hres
)) {
10621 This
->typeattr
.wTypeFlags
= old_flags
;
10628 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10631 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10633 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10636 return E_INVALIDARG
;
10638 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10643 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10646 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10648 TRACE("%p %d\n", This
, helpContext
);
10650 This
->dwHelpContext
= helpContext
;
10655 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10656 WORD majorVerNum
, WORD minorVerNum
)
10658 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10660 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10662 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10663 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10668 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10669 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10671 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10673 ITypeLib
*container
;
10674 TLBRefType
*ref_type
;
10676 TYPEATTR
*typeattr
;
10680 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10682 if (!typeInfo
|| !refType
)
10683 return E_INVALIDARG
;
10685 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10689 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10690 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10692 ITypeLib_Release(container
);
10694 *refType
= target
->hreftype
;
10699 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10700 if (FAILED(hres
)) {
10701 ITypeLib_Release(container
);
10705 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10706 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10707 implib
->lcid
== libattr
->lcid
&&
10708 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10709 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10713 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10714 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10716 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10717 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10718 implib
->name
= SysAllocString(our_container
->path
);
10720 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10721 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10723 implib
->name
= NULL
;
10724 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10728 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10729 implib
->lcid
= libattr
->lcid
;
10730 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10731 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10733 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10736 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10737 ITypeLib_Release(container
);
10739 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10744 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10745 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10746 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10747 ref_type
->tkind
== typeattr
->typekind
)
10752 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10753 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10755 ref_type
->tkind
= typeattr
->typekind
;
10756 ref_type
->pImpTLInfo
= implib
;
10757 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10759 ref_type
->index
= TLB_REF_USE_GUID
;
10761 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10763 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10766 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10768 *refType
= ref_type
->reference
| 0x1;
10770 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10771 This
->pTypeLib
->dispatch_href
= *refType
;
10776 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10777 UINT index
, FUNCDESC
*funcDesc
)
10779 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10780 TLBFuncDesc tmp_func_desc
, *func_desc
;
10785 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10787 if (!funcDesc
|| funcDesc
->oVft
& 3)
10788 return E_INVALIDARG
;
10790 switch (This
->typeattr
.typekind
) {
10792 if (funcDesc
->funckind
!= FUNC_STATIC
)
10793 return TYPE_E_BADMODULEKIND
;
10795 case TKIND_DISPATCH
:
10796 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10797 return TYPE_E_BADMODULEKIND
;
10800 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10801 return TYPE_E_BADMODULEKIND
;
10804 if (index
> This
->typeattr
.cFuncs
)
10805 return TYPE_E_ELEMENTNOTFOUND
;
10807 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10808 !funcDesc
->cParams
)
10809 return TYPE_E_INCONSISTENTPROPFUNCS
;
10812 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10813 funcDesc
->oVft
% 8 != 0)
10814 return E_INVALIDARG
;
10817 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10818 TLBFuncDesc_Constructor(&tmp_func_desc
);
10820 tmp_func_desc
.funcdesc
= *funcDesc
;
10822 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10823 tmp_func_desc
.funcdesc
.oVft
|= 1;
10825 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10826 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10827 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10829 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10830 tmp_func_desc
.funcdesc
.cScodes
= 0;
10833 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10834 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10835 buf_size
+= sizeof(ELEMDESC
);
10836 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10838 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10839 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10841 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10842 if (FAILED(hres
)) {
10843 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10844 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10848 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10849 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10850 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10851 if (FAILED(hres
)) {
10852 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10853 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10856 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10857 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10858 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10859 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10860 if (FAILED(hres
)) {
10861 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10862 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10868 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10870 if (This
->funcdescs
) {
10871 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10872 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10874 if (index
< This
->typeattr
.cFuncs
) {
10875 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10876 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10877 func_desc
= This
->funcdescs
+ index
;
10879 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10881 /* move custdata lists to the new memory location */
10882 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10884 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
10887 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10889 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10890 list_init(&func_desc
->custdata_list
);
10892 ++This
->typeattr
.cFuncs
;
10894 This
->needs_layout
= TRUE
;
10899 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10900 UINT index
, HREFTYPE refType
)
10902 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10903 TLBImplType
*impl_type
;
10906 TRACE("%p %u %d\n", This
, index
, refType
);
10908 switch(This
->typeattr
.typekind
){
10909 case TKIND_COCLASS
: {
10911 FIXME("Unhandled index: -1\n");
10915 if(index
!= This
->typeattr
.cImplTypes
)
10916 return TYPE_E_ELEMENTNOTFOUND
;
10920 case TKIND_INTERFACE
:
10921 case TKIND_DISPATCH
:
10922 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10923 return TYPE_E_ELEMENTNOTFOUND
;
10926 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10930 if (This
->impltypes
){
10933 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10934 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10936 if (index
< This
->typeattr
.cImplTypes
) {
10937 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10938 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10939 impl_type
= This
->impltypes
+ index
;
10941 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10943 /* move custdata lists to the new memory location */
10944 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10946 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
10949 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10951 memset(impl_type
, 0, sizeof(TLBImplType
));
10952 TLBImplType_Constructor(impl_type
);
10953 impl_type
->hRef
= refType
;
10955 ++This
->typeattr
.cImplTypes
;
10957 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10958 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10960 hres
= ICreateTypeInfo2_LayOut(iface
);
10967 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10968 UINT index
, INT implTypeFlags
)
10970 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10971 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10973 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10975 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10976 return TYPE_E_BADMODULEKIND
;
10978 if (index
>= This
->typeattr
.cImplTypes
)
10979 return TYPE_E_ELEMENTNOTFOUND
;
10981 impl_type
->implflags
= implTypeFlags
;
10986 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10989 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10991 TRACE("%p %d\n", This
, alignment
);
10993 This
->typeattr
.cbAlignment
= alignment
;
10998 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
11001 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11003 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
11006 return E_INVALIDARG
;
11008 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
11010 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
11015 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
11016 UINT index
, VARDESC
*varDesc
)
11018 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11019 TLBVarDesc
*var_desc
;
11022 TRACE("%p %u %p\n", This
, index
, varDesc
);
11024 if (This
->vardescs
){
11027 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
11028 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
11030 if (index
< This
->typeattr
.cVars
) {
11031 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
11032 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
11033 var_desc
= This
->vardescs
+ index
;
11035 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
11037 /* move custdata lists to the new memory location */
11038 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
11040 TLB_relink_custdata(&This
->vardescs
[i
].custdata_list
);
11043 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
11045 TLBVarDesc_Constructor(var_desc
);
11046 hr
= TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
11049 var_desc
->vardesc
= *var_desc
->vardesc_create
;
11051 ++This
->typeattr
.cVars
;
11053 This
->needs_layout
= TRUE
;
11058 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
11059 UINT index
, LPOLESTR
*names
, UINT numNames
)
11061 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11062 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11065 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
11068 return E_INVALIDARG
;
11070 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
11071 return TYPE_E_ELEMENTNOTFOUND
;
11073 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
11074 if(numNames
> func_desc
->funcdesc
.cParams
)
11075 return TYPE_E_ELEMENTNOTFOUND
;
11077 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
11078 return TYPE_E_ELEMENTNOTFOUND
;
11080 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
11081 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
11082 if (iter
->Name
&& !wcscmp(TLB_get_bstr(iter
->Name
), *names
)) {
11083 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
11084 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
11085 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
11087 return TYPE_E_AMBIGUOUSNAME
;
11091 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
11093 for (i
= 1; i
< numNames
; ++i
) {
11094 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
11095 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
11101 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
11102 UINT index
, LPOLESTR name
)
11104 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11106 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
11109 return E_INVALIDARG
;
11111 if(index
>= This
->typeattr
.cVars
)
11112 return TYPE_E_ELEMENTNOTFOUND
;
11114 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11118 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
11119 TYPEDESC
*tdescAlias
)
11121 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11124 TRACE("%p %p\n", This
, tdescAlias
);
11127 return E_INVALIDARG
;
11129 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
11130 return TYPE_E_BADMODULEKIND
;
11132 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
11136 heap_free(This
->tdescAlias
);
11137 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
11138 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
11143 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
11144 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
11146 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11147 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
11151 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
11152 UINT index
, LPOLESTR docString
)
11154 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11155 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11157 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11160 return E_INVALIDARG
;
11162 if(index
>= This
->typeattr
.cFuncs
)
11163 return TYPE_E_ELEMENTNOTFOUND
;
11165 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11170 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
11171 UINT index
, LPOLESTR docString
)
11173 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11174 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11176 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11179 return E_INVALIDARG
;
11181 if(index
>= This
->typeattr
.cVars
)
11182 return TYPE_E_ELEMENTNOTFOUND
;
11184 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11189 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
11190 UINT index
, DWORD helpContext
)
11192 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11193 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11195 TRACE("%p %u %d\n", This
, index
, helpContext
);
11197 if(index
>= This
->typeattr
.cFuncs
)
11198 return TYPE_E_ELEMENTNOTFOUND
;
11200 func_desc
->helpcontext
= helpContext
;
11205 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
11206 UINT index
, DWORD helpContext
)
11208 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11209 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11211 TRACE("%p %u %d\n", This
, index
, helpContext
);
11213 if(index
>= This
->typeattr
.cVars
)
11214 return TYPE_E_ELEMENTNOTFOUND
;
11216 var_desc
->HelpContext
= helpContext
;
11221 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
11222 UINT index
, BSTR bstrMops
)
11224 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11225 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
11229 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
11232 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11234 TRACE("%p %p\n", This
, idlDesc
);
11237 return E_INVALIDARG
;
11239 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11240 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11245 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11247 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11248 ITypeInfo2
*tinfo
= &This
->ITypeInfo2_iface
;
11249 TLBFuncDesc
*func_desc
;
11250 UINT user_vft
= 0, i
, depth
= 0;
11251 HRESULT hres
= S_OK
;
11253 TRACE("%p\n", This
);
11255 This
->needs_layout
= FALSE
;
11257 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11262 hres
= ITypeInfo2_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11264 if (SUCCEEDED(hres
)) {
11265 hres
= ITypeInfo2_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11267 if (SUCCEEDED(hres
)) {
11268 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11269 if (FAILED(hres
)) {
11270 ITypeInfo_Release(inh
);
11273 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11274 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11278 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11279 if(SUCCEEDED(hres
)){
11281 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11282 if(SUCCEEDED(hres
)){
11283 ITypeInfo_Release(inh
);
11287 }while(SUCCEEDED(hres
));
11290 ITypeInfo_Release(inh
);
11291 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11292 This
->typeattr
.cbSizeVft
= 0;
11296 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11297 This
->typeattr
.cbSizeVft
= 0;
11301 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11302 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11304 This
->typeattr
.cbSizeVft
= 0;
11306 func_desc
= This
->funcdescs
;
11308 while (i
< This
->typeattr
.cFuncs
) {
11309 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11310 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11312 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11313 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11315 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11317 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11320 BOOL reset
= FALSE
;
11322 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11324 iter
= This
->funcdescs
;
11325 while (j
< This
->typeattr
.cFuncs
) {
11326 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11328 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11331 ++func_desc
->funcdesc
.memid
;
11332 iter
= This
->funcdescs
;
11345 if (user_vft
> This
->typeattr
.cbSizeVft
)
11346 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11348 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11349 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11350 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11352 BOOL reset
= FALSE
;
11355 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11357 iter
= This
->vardescs
;
11358 while (j
< This
->typeattr
.cVars
) {
11359 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11361 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11364 ++var_desc
->vardesc
.memid
;
11365 iter
= This
->vardescs
;
11378 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11381 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11384 TRACE("%p %u\n", This
, index
);
11386 if (index
>= This
->typeattr
.cFuncs
)
11387 return TYPE_E_ELEMENTNOTFOUND
;
11389 typeinfo_release_funcdesc(&This
->funcdescs
[index
]);
11391 --This
->typeattr
.cFuncs
;
11392 if (index
!= This
->typeattr
.cFuncs
)
11394 memmove(This
->funcdescs
+ index
, This
->funcdescs
+ index
+ 1,
11395 sizeof(*This
->funcdescs
) * (This
->typeattr
.cFuncs
- index
));
11396 for (i
= index
; i
< This
->typeattr
.cFuncs
; ++i
)
11397 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
11400 This
->needs_layout
= TRUE
;
11405 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11406 MEMBERID memid
, INVOKEKIND invKind
)
11408 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11409 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11413 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11416 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11417 FIXME("%p %u - stub\n", This
, index
);
11421 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11424 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11425 FIXME("%p %x - stub\n", This
, memid
);
11429 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11432 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11435 TRACE("%p %u\n", This
, index
);
11437 if (index
>= This
->typeattr
.cImplTypes
)
11438 return TYPE_E_ELEMENTNOTFOUND
;
11440 TLB_FreeCustData(&This
->impltypes
[index
].custdata_list
);
11441 --This
->typeattr
.cImplTypes
;
11443 if (index
< This
->typeattr
.cImplTypes
)
11445 memmove(This
->impltypes
+ index
, This
->impltypes
+ index
+ 1, (This
->typeattr
.cImplTypes
- index
) *
11446 sizeof(*This
->impltypes
));
11447 for (i
= index
; i
< This
->typeattr
.cImplTypes
; ++i
)
11448 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
11454 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11455 REFGUID guid
, VARIANT
*varVal
)
11459 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11461 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11463 if (!guid
|| !varVal
)
11464 return E_INVALIDARG
;
11466 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11468 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11471 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11472 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11474 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11475 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11479 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11480 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11482 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11483 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11487 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11488 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11490 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11491 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11495 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11496 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11498 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11499 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11503 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11504 ULONG helpStringContext
)
11506 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11508 TRACE("%p %u\n", This
, helpStringContext
);
11510 This
->dwHelpStringContext
= helpStringContext
;
11515 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11516 UINT index
, ULONG helpStringContext
)
11518 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11519 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11523 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11524 UINT index
, ULONG helpStringContext
)
11526 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11527 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11531 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11533 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11534 FIXME("%p - stub\n", This
);
11538 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11541 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11543 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11546 return E_INVALIDARG
;
11548 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11553 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11554 ICreateTypeInfo2_fnQueryInterface
,
11555 ICreateTypeInfo2_fnAddRef
,
11556 ICreateTypeInfo2_fnRelease
,
11557 ICreateTypeInfo2_fnSetGuid
,
11558 ICreateTypeInfo2_fnSetTypeFlags
,
11559 ICreateTypeInfo2_fnSetDocString
,
11560 ICreateTypeInfo2_fnSetHelpContext
,
11561 ICreateTypeInfo2_fnSetVersion
,
11562 ICreateTypeInfo2_fnAddRefTypeInfo
,
11563 ICreateTypeInfo2_fnAddFuncDesc
,
11564 ICreateTypeInfo2_fnAddImplType
,
11565 ICreateTypeInfo2_fnSetImplTypeFlags
,
11566 ICreateTypeInfo2_fnSetAlignment
,
11567 ICreateTypeInfo2_fnSetSchema
,
11568 ICreateTypeInfo2_fnAddVarDesc
,
11569 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11570 ICreateTypeInfo2_fnSetVarName
,
11571 ICreateTypeInfo2_fnSetTypeDescAlias
,
11572 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11573 ICreateTypeInfo2_fnSetFuncDocString
,
11574 ICreateTypeInfo2_fnSetVarDocString
,
11575 ICreateTypeInfo2_fnSetFuncHelpContext
,
11576 ICreateTypeInfo2_fnSetVarHelpContext
,
11577 ICreateTypeInfo2_fnSetMops
,
11578 ICreateTypeInfo2_fnSetTypeIdldesc
,
11579 ICreateTypeInfo2_fnLayOut
,
11580 ICreateTypeInfo2_fnDeleteFuncDesc
,
11581 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11582 ICreateTypeInfo2_fnDeleteVarDesc
,
11583 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11584 ICreateTypeInfo2_fnDeleteImplType
,
11585 ICreateTypeInfo2_fnSetCustData
,
11586 ICreateTypeInfo2_fnSetFuncCustData
,
11587 ICreateTypeInfo2_fnSetParamCustData
,
11588 ICreateTypeInfo2_fnSetVarCustData
,
11589 ICreateTypeInfo2_fnSetImplTypeCustData
,
11590 ICreateTypeInfo2_fnSetHelpStringContext
,
11591 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11592 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11593 ICreateTypeInfo2_fnInvalidate
,
11594 ICreateTypeInfo2_fnSetName
11597 /******************************************************************************
11598 * ClearCustData (OLEAUT32.171)
11600 * Clear a custom data type's data.
11603 * lpCust [I] The custom data type instance
11608 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11610 if (lpCust
&& lpCust
->cCustData
)
11612 if (lpCust
->prgCustData
)
11616 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11617 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11619 CoTaskMemFree(lpCust
->prgCustData
);
11620 lpCust
->prgCustData
= NULL
;
11622 lpCust
->cCustData
= 0;