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
)))
632 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
635 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
636 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
641 /* Set the human-readable name of the typelib to
642 the typelib's doc, if it exists, else to the typelib's name. */
643 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, &libName
, &doc
, NULL
, NULL
)))
645 else if (doc
|| libName
)
647 WCHAR
*name
= doc
? doc
: libName
;
649 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
650 (BYTE
*)name
, (lstrlenW(name
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
654 SysFreeString(libName
);
657 /* Make up the name of the typelib path subkey */
658 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
660 /* Create the typelib path subkey */
661 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
662 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
664 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
665 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
673 /* Create the flags subkey */
674 if (res
== S_OK
&& RegCreateKeyExW(key
, L
"FLAGS", 0, NULL
, 0,
675 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
679 /* FIXME: is %u correct? */
680 swprintf(buf
, ARRAY_SIZE(buf
), L
"%u", attr
->wLibFlags
);
681 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
682 (BYTE
*)buf
, (lstrlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
690 /* create the helpdir subkey */
691 if (res
== S_OK
&& RegCreateKeyExW(key
, L
"HELPDIR", 0, NULL
, 0,
692 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
694 BSTR freeHelpDir
= NULL
;
697 /* if we created a new key, and helpDir was null, set the helpdir
698 to the directory which contains the typelib. However,
699 if we just opened an existing key, we leave the helpdir alone */
700 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
701 szHelpDir
= freeHelpDir
= SysAllocString(szFullPath
);
702 file_name
= wcsrchr(szHelpDir
, '\\');
703 if (file_name
&& file_name
[1]) {
704 /* possible remove a numeric \index (resource-id) */
705 WCHAR
*end_ptr
= file_name
+ 1;
706 while ('0' <= *end_ptr
&& *end_ptr
<= '9') end_ptr
++;
710 file_name
= wcsrchr(szHelpDir
, '\\');
717 /* if we have an szHelpDir, set it! */
718 if (szHelpDir
!= NULL
) {
719 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
720 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
725 SysFreeString(freeHelpDir
);
736 /* register OLE Automation-compatible interfaces for this typelib */
737 types
= ITypeLib_GetTypeInfoCount(ptlib
);
738 for (tidx
=0; tidx
<types
; tidx
++) {
739 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
740 LPOLESTR name
= NULL
;
741 ITypeInfo
*tinfo
= NULL
;
743 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
746 case TKIND_INTERFACE
:
747 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
748 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
752 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
753 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
757 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
762 TYPEATTR
*tattr
= NULL
;
763 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
766 TRACE_(typelib
)("guid=%s, flags=%04x (",
767 debugstr_guid(&tattr
->guid
),
770 if (TRACE_ON(typelib
)) {
771 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
791 /* Register all dispinterfaces (which includes dual interfaces) and
792 oleautomation interfaces */
793 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
794 kind
== TKIND_DISPATCH
)
797 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
799 /* register interface<->typelib coupling */
800 TLB_register_interface(attr
, name
, tattr
, 0);
802 /* register TLBs into the opposite registry view, too */
803 if(opposite
== KEY_WOW64_32KEY
||
804 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
805 TLB_register_interface(attr
, name
, tattr
, opposite
);
808 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
811 ITypeInfo_Release(tinfo
);
818 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
823 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
825 WCHAR subKeyName
[50];
828 /* the path to the type */
829 get_interface_key( guid
, subKeyName
);
831 /* Delete its bits */
832 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
835 RegDeleteKeyW(subKey
, L
"ProxyStubClsid");
836 RegDeleteKeyW(subKey
, L
"ProxyStubClsid32");
837 RegDeleteKeyW(subKey
, L
"TypeLib");
839 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
842 /******************************************************************************
843 * UnRegisterTypeLib [OLEAUT32.186]
844 * Removes information about a type library from the System Registry
851 HRESULT WINAPI
UnRegisterTypeLib(
852 REFGUID libid
, /* [in] Guid of the library */
853 WORD wVerMajor
, /* [in] major version */
854 WORD wVerMinor
, /* [in] minor version */
855 LCID lcid
, /* [in] locale id */
858 BSTR tlibPath
= NULL
;
861 WCHAR subKeyName
[50];
864 BOOL deleteOtherStuff
;
866 TYPEATTR
* typeAttr
= NULL
;
868 ITypeInfo
* typeInfo
= NULL
;
869 ITypeLib
* typeLib
= NULL
;
872 TRACE("(IID: %s)\n",debugstr_guid(libid
));
874 /* Create the path to the key */
875 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
877 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
879 TRACE("Unsupported syskind %i\n", syskind
);
880 result
= E_INVALIDARG
;
884 /* get the path to the typelib on disk */
885 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
886 result
= E_INVALIDARG
;
890 /* Try and open the key to the type library. */
891 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
892 result
= E_INVALIDARG
;
896 /* Try and load the type library */
897 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
898 result
= TYPE_E_INVALIDSTATE
;
902 /* remove any types registered with this typelib */
903 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
904 for (i
=0; i
<numTypes
; i
++) {
905 /* get the kind of type */
906 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
910 /* skip non-interfaces, and get type info for the type */
911 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
914 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
917 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
921 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
922 kind
== TKIND_DISPATCH
)
925 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
927 TLB_unregister_interface(&typeAttr
->guid
, 0);
929 /* unregister TLBs into the opposite registry view, too */
930 if(opposite
== KEY_WOW64_32KEY
||
931 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
932 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
937 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
939 if (typeInfo
) ITypeInfo_Release(typeInfo
);
943 /* Now, delete the type library path subkey */
944 get_lcid_subkey( lcid
, syskind
, subKeyName
);
945 RegDeleteKeyW(key
, subKeyName
);
946 *wcsrchr( subKeyName
, '\\' ) = 0; /* remove last path component */
947 RegDeleteKeyW(key
, subKeyName
);
949 /* check if there is anything besides the FLAGS/HELPDIR keys.
950 If there is, we don't delete them */
951 tmpLength
= ARRAY_SIZE(subKeyName
);
952 deleteOtherStuff
= TRUE
;
954 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
955 tmpLength
= ARRAY_SIZE(subKeyName
);
957 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
958 if (!wcscmp(subKeyName
, L
"FLAGS")) continue;
959 if (!wcscmp(subKeyName
, L
"HELPDIR")) continue;
960 deleteOtherStuff
= FALSE
;
964 /* only delete the other parts of the key if we're absolutely sure */
965 if (deleteOtherStuff
) {
966 RegDeleteKeyW(key
, L
"FLAGS");
967 RegDeleteKeyW(key
, L
"HELPDIR");
971 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
972 *wcsrchr( keyName
, '\\' ) = 0; /* remove last path component */
973 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
977 SysFreeString(tlibPath
);
978 if (typeLib
) ITypeLib_Release(typeLib
);
979 if (key
) RegCloseKey(key
);
983 /******************************************************************************
984 * RegisterTypeLibForUser [OLEAUT32.442]
985 * Adds information about a type library to the user registry
987 * Docs: ITypeLib FAR * ptlib
988 * Docs: OLECHAR FAR* szFullPath
989 * Docs: OLECHAR FAR* szHelpDir
995 HRESULT WINAPI
RegisterTypeLibForUser(
996 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
997 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
998 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1001 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1002 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1003 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1006 /******************************************************************************
1007 * UnRegisterTypeLibForUser [OLEAUT32.443]
1008 * Removes information about a type library from the user registry
1014 HRESULT WINAPI
UnRegisterTypeLibForUser(
1015 REFGUID libid
, /* [in] GUID of the library */
1016 WORD wVerMajor
, /* [in] major version */
1017 WORD wVerMinor
, /* [in] minor version */
1018 LCID lcid
, /* [in] locale id */
1021 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1022 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1023 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1026 /*======================= ITypeLib implementation =======================*/
1028 typedef struct tagTLBGuid
{
1035 typedef struct tagTLBCustData
1042 /* data structure for import typelibs */
1043 typedef struct tagTLBImpLib
1045 int offset
; /* offset in the file (MSFT)
1046 offset in nametable (SLTG)
1047 just used to identify library while reading
1049 TLBGuid
*guid
; /* libid */
1050 BSTR name
; /* name */
1052 LCID lcid
; /* lcid of imported typelib */
1054 WORD wVersionMajor
; /* major version number */
1055 WORD wVersionMinor
; /* minor version number */
1057 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1058 NULL if not yet loaded */
1062 typedef struct tagTLBString
{
1068 /* internal ITypeLib data */
1069 typedef struct tagITypeLibImpl
1071 ITypeLib2 ITypeLib2_iface
;
1072 ITypeComp ITypeComp_iface
;
1073 ICreateTypeLib2 ICreateTypeLib2_iface
;
1084 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1085 * exported to the application as a UNICODE string.
1087 struct list string_list
;
1088 struct list name_list
;
1089 struct list guid_list
;
1091 const TLBString
*Name
;
1092 const TLBString
*DocString
;
1093 const TLBString
*HelpFile
;
1094 const TLBString
*HelpStringDll
;
1095 DWORD dwHelpContext
;
1096 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1097 struct tagITypeInfoImpl
**typeinfos
;
1098 struct list custdata_list
;
1099 struct list implib_list
;
1100 int ctTypeDesc
; /* number of items in type desc array */
1101 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1102 library. Only used while reading MSFT
1104 struct list ref_list
; /* list of ref types in this typelib */
1105 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1108 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1114 static const ITypeLib2Vtbl tlbvt
;
1115 static const ITypeCompVtbl tlbtcvt
;
1116 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1118 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1120 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1123 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1125 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1128 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1130 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1133 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1135 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1138 /* ITypeLib methods */
1139 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1140 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1142 /*======================= ITypeInfo implementation =======================*/
1144 /* data for referenced types */
1145 typedef struct tagTLBRefType
1147 INT index
; /* Type index for internal ref or for external ref
1148 it the format is SLTG. -2 indicates to
1152 TLBGuid
*guid
; /* guid of the referenced type */
1153 /* if index == TLB_REF_USE_GUID */
1155 HREFTYPE reference
; /* The href of this ref */
1156 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1157 TLB_REF_INTERNAL for internal refs
1158 TLB_REF_NOT_FOUND for broken refs */
1163 #define TLB_REF_USE_GUID -2
1165 #define TLB_REF_INTERNAL (void*)-2
1166 #define TLB_REF_NOT_FOUND (void*)-1
1168 /* internal Parameter data */
1169 typedef struct tagTLBParDesc
1171 const TLBString
*Name
;
1172 struct list custdata_list
;
1175 /* internal Function data */
1176 typedef struct tagTLBFuncDesc
1178 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1179 const TLBString
*Name
; /* the name of this function */
1180 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1182 int HelpStringContext
;
1183 const TLBString
*HelpString
;
1184 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1185 struct list custdata_list
;
1188 /* internal Variable data */
1189 typedef struct tagTLBVarDesc
1191 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1192 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1193 const TLBString
*Name
; /* the name of this variable */
1195 int HelpStringContext
;
1196 const TLBString
*HelpString
;
1197 struct list custdata_list
;
1200 /* internal implemented interface data */
1201 typedef struct tagTLBImplType
1203 HREFTYPE hRef
; /* hRef of interface */
1204 int implflags
; /* IMPLFLAG_*s */
1205 struct list custdata_list
;
1208 /* internal TypeInfo data */
1209 typedef struct tagITypeInfoImpl
1211 ITypeInfo2 ITypeInfo2_iface
;
1212 ITypeComp ITypeComp_iface
;
1213 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1215 BOOL not_attached_to_typelib
;
1220 TYPEDESC
*tdescAlias
;
1222 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1223 int index
; /* index in this typelib; */
1224 HREFTYPE hreftype
; /* hreftype for app object binding */
1225 /* type libs seem to store the doc strings in ascii
1226 * so why should we do it in unicode?
1228 const TLBString
*Name
;
1229 const TLBString
*DocString
;
1230 const TLBString
*DllName
;
1231 const TLBString
*Schema
;
1232 DWORD dwHelpContext
;
1233 DWORD dwHelpStringContext
;
1236 TLBFuncDesc
*funcdescs
;
1239 TLBVarDesc
*vardescs
;
1241 /* Implemented Interfaces */
1242 TLBImplType
*impltypes
;
1244 struct list
*pcustdata_list
;
1245 struct list custdata_list
;
1248 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1250 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1253 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1255 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1258 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1260 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1263 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1265 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1268 static const ITypeInfo2Vtbl tinfvt
;
1269 static const ITypeCompVtbl tcompvt
;
1270 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1272 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1273 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1275 typedef struct tagTLBContext
1277 unsigned int oStart
; /* start of TLB in file */
1278 unsigned int pos
; /* current pos */
1279 unsigned int length
; /* total length */
1280 void *mapping
; /* memory mapping */
1281 MSFT_SegDir
* pTblDir
;
1282 ITypeLibImpl
* pLibInfo
;
1286 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1288 return str
!= NULL
? str
->str
: NULL
;
1291 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1295 return memcmp(left
, str
->str
, len
);
1298 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1300 return guid
!= NULL
? &guid
->guid
: NULL
;
1303 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1305 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1308 static int get_ptr_size(SYSKIND syskind
)
1318 WARN("Unhandled syskind: 0x%x\n", syskind
);
1325 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1326 if (pTD
->vt
& VT_RESERVED
)
1327 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1328 if (pTD
->vt
& VT_BYREF
)
1329 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1330 if (pTD
->vt
& VT_ARRAY
)
1331 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1332 if (pTD
->vt
& VT_VECTOR
)
1333 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1334 switch(pTD
->vt
& VT_TYPEMASK
) {
1335 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1336 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1337 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1338 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1339 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1340 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1341 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1342 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1343 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1344 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1345 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1346 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1347 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1348 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1349 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1350 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1351 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1352 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1353 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1354 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1355 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1356 pTD
->u
.hreftype
); break;
1357 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1358 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1359 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1360 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1362 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1363 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1365 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1366 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1367 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1370 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1374 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1376 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1377 dump_TypeDesc(&edesc
->tdesc
,buf
);
1378 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1379 MESSAGE("\t\tu.paramdesc.wParamFlags");
1380 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1381 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1382 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1383 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1384 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1385 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1386 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1387 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1388 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1390 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1392 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1393 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1394 MESSAGE("Param %d:\n",i
);
1395 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1397 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1398 switch (funcdesc
->funckind
) {
1399 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1400 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1401 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1402 case FUNC_STATIC
: MESSAGE("static");break;
1403 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1404 default: MESSAGE("unknown");break;
1406 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1407 switch (funcdesc
->invkind
) {
1408 case INVOKE_FUNC
: MESSAGE("func");break;
1409 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1410 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1411 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1413 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1414 switch (funcdesc
->callconv
) {
1415 case CC_CDECL
: MESSAGE("cdecl");break;
1416 case CC_PASCAL
: MESSAGE("pascal");break;
1417 case CC_STDCALL
: MESSAGE("stdcall");break;
1418 case CC_SYSCALL
: MESSAGE("syscall");break;
1421 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1422 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1423 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1425 MESSAGE("\telemdescFunc (return value type):\n");
1426 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1429 static const char * const typekind_desc
[] =
1442 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1445 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1446 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1447 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1450 dump_FUNCDESC(&(pfd
->funcdesc
));
1452 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1453 if(pfd
->Entry
== NULL
)
1454 MESSAGE("\tentry: (null)\n");
1455 else if(pfd
->Entry
== (void*)-1)
1456 MESSAGE("\tentry: invalid\n");
1457 else if(IS_INTRESOURCE(pfd
->Entry
))
1458 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1460 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1462 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1466 dump_TLBFuncDescOne(pfd
);
1471 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1475 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1481 static void dump_TLBImpLib(const TLBImpLib
*import
)
1483 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1484 debugstr_w(import
->name
));
1485 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1486 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1489 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1493 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1495 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1496 if(ref
->index
== -1)
1497 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1499 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1501 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1503 TRACE_(typelib
)("in lib\n");
1504 dump_TLBImpLib(ref
->pImpTLInfo
);
1509 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1514 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1515 impl
->hRef
, impl
->implflags
);
1521 static void dump_DispParms(const DISPPARAMS
* pdp
)
1525 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1527 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1529 TRACE("named args:\n");
1530 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1531 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1534 if (pdp
->cArgs
&& pdp
->rgvarg
)
1537 for (index
= 0; index
< pdp
->cArgs
; index
++)
1538 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1542 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1544 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1545 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1546 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1547 TRACE("kind:%s\n", typekind_desc
[pty
->typeattr
.typekind
]);
1548 TRACE("fct:%u var:%u impl:%u\n", pty
->typeattr
.cFuncs
, pty
->typeattr
.cVars
, pty
->typeattr
.cImplTypes
);
1549 TRACE("wTypeFlags: 0x%04x\n", pty
->typeattr
.wTypeFlags
);
1550 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1551 if (pty
->typeattr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1553 dump_TLBFuncDesc(pty
->funcdescs
, pty
->typeattr
.cFuncs
);
1554 dump_TLBVarDesc(pty
->vardescs
, pty
->typeattr
.cVars
);
1555 dump_TLBImplType(pty
->impltypes
, pty
->typeattr
.cImplTypes
);
1558 static void dump_VARDESC(const VARDESC
*v
)
1560 MESSAGE("memid %d\n",v
->memid
);
1561 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1562 MESSAGE("oInst %d\n",v
->u
.oInst
);
1563 dump_ELEMDESC(&(v
->elemdescVar
));
1564 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1565 MESSAGE("varkind %d\n",v
->varkind
);
1568 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1570 /* VT_LPWSTR is largest type that, may appear in type description */
1571 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1572 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1573 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1574 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1575 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1576 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1577 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1578 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1581 static void TLB_abort(void)
1586 /* returns the size required for a deep copy of a typedesc into a
1588 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1592 if (alloc_initial_space
)
1593 size
+= sizeof(TYPEDESC
);
1599 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1602 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1603 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1609 /* deep copy a typedesc into a flat buffer */
1610 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1615 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1624 dest
->u
.lptdesc
= buffer
;
1625 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1628 dest
->u
.lpadesc
= buffer
;
1629 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1630 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1631 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1637 /* free custom data allocated by MSFT_CustData */
1638 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1640 TLBCustData
*cd
, *cdn
;
1641 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1643 list_remove(&cd
->entry
);
1644 VariantClear(&cd
->data
);
1649 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1654 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1655 ret
= SysAllocStringLen(NULL
, len
- 1);
1656 if (!ret
) return ret
;
1657 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1661 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(ITypeInfoImpl
*typeinfo
, MEMBERID memid
)
1665 for (i
= 0; i
< typeinfo
->typeattr
.cFuncs
; ++i
)
1667 if (typeinfo
->funcdescs
[i
].funcdesc
.memid
== memid
)
1668 return &typeinfo
->funcdescs
[i
];
1674 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid_invkind(ITypeInfoImpl
*typeinfo
, MEMBERID memid
, INVOKEKIND invkind
)
1678 for (i
= 0; i
< typeinfo
->typeattr
.cFuncs
; ++i
)
1680 if (typeinfo
->funcdescs
[i
].funcdesc
.memid
== memid
&& typeinfo
->funcdescs
[i
].funcdesc
.invkind
== invkind
)
1681 return &typeinfo
->funcdescs
[i
];
1687 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(ITypeInfoImpl
*typeinfo
, MEMBERID memid
)
1691 for (i
= 0; i
< typeinfo
->typeattr
.cVars
; ++i
)
1693 if (typeinfo
->vardescs
[i
].vardesc
.memid
== memid
)
1694 return &typeinfo
->vardescs
[i
];
1700 static inline TLBVarDesc
*TLB_get_vardesc_by_name(ITypeInfoImpl
*typeinfo
, const OLECHAR
*name
)
1704 for (i
= 0; i
< typeinfo
->typeattr
.cVars
; ++i
)
1706 if (!lstrcmpiW(TLB_get_bstr(typeinfo
->vardescs
[i
].Name
), name
))
1707 return &typeinfo
->vardescs
[i
];
1713 static inline TLBCustData
*TLB_get_custdata_by_guid(const struct list
*custdata_list
, REFGUID guid
)
1715 TLBCustData
*cust_data
;
1716 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1717 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1722 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeLibImpl
*typelib
, const OLECHAR
*name
)
1726 for (i
= 0; i
< typelib
->TypeInfoCount
; ++i
)
1728 if (!lstrcmpiW(TLB_get_bstr(typelib
->typeinfos
[i
]->Name
), name
))
1729 return typelib
->typeinfos
[i
];
1735 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1737 list_init(&var_desc
->custdata_list
);
1740 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1744 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1749 TLBVarDesc_Constructor(&ret
[n
-1]);
1756 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1760 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1765 list_init(&ret
[n
-1].custdata_list
);
1772 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1774 list_init(&func_desc
->custdata_list
);
1777 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1781 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1786 TLBFuncDesc_Constructor(&ret
[n
-1]);
1793 static void TLBImplType_Constructor(TLBImplType
*impl
)
1795 list_init(&impl
->custdata_list
);
1798 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1802 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1807 TLBImplType_Constructor(&ret
[n
-1]);
1814 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1815 const GUID
*new_guid
, HREFTYPE hreftype
)
1819 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1820 if (IsEqualGUID(&guid
->guid
, new_guid
))
1824 guid
= heap_alloc(sizeof(TLBGuid
));
1828 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1829 guid
->hreftype
= hreftype
;
1831 list_add_tail(guid_list
, &guid
->entry
);
1836 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1838 TLBCustData
*cust_data
;
1850 return DISP_E_BADVARTYPE
;
1853 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1856 cust_data
= heap_alloc(sizeof(TLBCustData
));
1858 return E_OUTOFMEMORY
;
1860 cust_data
->guid
= tlbguid
;
1861 VariantInit(&cust_data
->data
);
1863 list_add_tail(custdata_list
, &cust_data
->entry
);
1865 VariantClear(&cust_data
->data
);
1867 return VariantCopy(&cust_data
->data
, var
);
1870 /* Used to update list pointers after list itself was moved. */
1871 static void TLB_relink_custdata(struct list
*custdata_list
)
1873 if (custdata_list
->prev
== custdata_list
->next
)
1874 list_init(custdata_list
);
1877 custdata_list
->prev
->next
= custdata_list
;
1878 custdata_list
->next
->prev
= custdata_list
;
1882 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1889 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1890 if (wcscmp(str
->str
, new_str
) == 0)
1894 str
= heap_alloc(sizeof(TLBString
));
1898 str
->str
= SysAllocString(new_str
);
1904 list_add_tail(string_list
, &str
->entry
);
1909 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1910 ULONG
*size
, WORD
*align
)
1916 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1920 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1922 ITypeInfo_Release(other
);
1927 *size
= attr
->cbSizeInstance
;
1929 *align
= attr
->cbAlignment
;
1931 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1932 ITypeInfo_Release(other
);
1937 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1938 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1940 ULONG i
, sub
, ptr_size
;
1943 ptr_size
= get_ptr_size(sys
);
1982 *size
= sizeof(DATE
);
1985 *size
= sizeof(VARIANT
);
1987 if(sys
== SYS_WIN32
)
1988 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1992 *size
= sizeof(DECIMAL
);
1999 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2000 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2001 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2006 case VT_USERDEFINED
:
2007 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2009 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2023 /**********************************************************************
2025 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2028 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2030 if (where
!= DO_NOT_SEEK
)
2032 where
+= pcx
->oStart
;
2033 if (where
> pcx
->length
)
2036 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2044 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2046 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2047 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2049 MSFT_Seek(pcx
, where
);
2050 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2051 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2056 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2061 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2062 FromLEDWords(buffer
, ret
);
2067 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2072 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2073 FromLEWords(buffer
, ret
);
2078 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2081 MSFT_GuidEntry entry
;
2084 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2086 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2089 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2091 guid
= heap_alloc(sizeof(TLBGuid
));
2093 guid
->offset
= offs
;
2094 guid
->guid
= entry
.guid
;
2095 guid
->hreftype
= entry
.hreftype
;
2097 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2099 offs
+= sizeof(MSFT_GuidEntry
);
2103 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2107 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2108 if(ret
->offset
== offset
){
2109 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2117 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2119 MSFT_NameIntro niName
;
2123 ERR_(typelib
)("bad offset %d\n", offset
);
2127 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2128 pcx
->pTblDir
->pNametab
.offset
+offset
);
2130 return niName
.hreftype
;
2133 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2136 MSFT_NameIntro intro
;
2138 int offs
= 0, lengthInChars
;
2140 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2144 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2147 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2148 intro
.namelen
&= 0xFF;
2149 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2151 len_piece
= (len_piece
+ 4) & ~0x3;
2155 string
= heap_alloc(len_piece
+ 1);
2156 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2157 string
[intro
.namelen
] = '\0';
2159 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2160 string
, -1, NULL
, 0);
2161 if (!lengthInChars
) {
2163 return E_UNEXPECTED
;
2166 tlbstr
= heap_alloc(sizeof(TLBString
));
2168 tlbstr
->offset
= offs
;
2169 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2170 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2174 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2180 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2184 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2185 if (tlbstr
->offset
== offset
) {
2186 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2194 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2198 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2199 if (tlbstr
->offset
== offset
) {
2200 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2209 * read a value and fill a VARIANT structure
2211 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2215 TRACE_(typelib
)("\n");
2217 if(offset
<0) { /* data are packed in here */
2218 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2219 V_I4(pVar
) = offset
& 0x3ffffff;
2222 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2223 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2224 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2225 switch (V_VT(pVar
)){
2226 case VT_EMPTY
: /* FIXME: is this right? */
2227 case VT_NULL
: /* FIXME: is this right? */
2228 case VT_I2
: /* this should not happen */
2239 case VT_VOID
: /* FIXME: is this right? */
2247 case VT_DECIMAL
: /* FIXME: is this right? */
2250 /* pointer types with known behaviour */
2253 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2255 V_BSTR(pVar
) = NULL
;
2257 ptr
= heap_alloc_zero(size
);
2258 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2259 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2260 /* FIXME: do we need a AtoW conversion here? */
2261 V_UNION(pVar
, bstrVal
[size
])='\0';
2262 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2267 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2274 case VT_USERDEFINED
:
2280 case VT_STREAMED_OBJECT
:
2281 case VT_STORED_OBJECT
:
2282 case VT_BLOB_OBJECT
:
2287 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2291 if(size
>0) /* (big|small) endian correct? */
2292 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2296 * create a linked list with custom data
2298 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2304 TRACE_(typelib
)("\n");
2306 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2310 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2311 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2312 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2313 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2314 list_add_head(custdata_list
, &pNew
->entry
);
2315 offset
= entry
.next
;
2320 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2323 pTd
->vt
=type
& VT_TYPEMASK
;
2325 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2327 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2330 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2332 return (invkind
== INVOKE_PROPERTYGET
||
2333 invkind
== INVOKE_PROPERTYPUT
||
2334 invkind
== INVOKE_PROPERTYPUTREF
);
2338 MSFT_DoFuncs(TLBContext
* pcx
,
2343 TLBFuncDesc
** pptfd
)
2346 * member information is stored in a data structure at offset
2347 * indicated by the memoffset field of the typeinfo structure
2348 * There are several distinctive parts.
2349 * The first part starts with a field that holds the total length
2350 * of this (first) part excluding this field. Then follow the records,
2351 * for each member there is one record.
2353 * The first entry is always the length of the record (including this
2355 * The rest of the record depends on the type of the member. If there is
2356 * a field indicating the member type (function, variable, interface, etc)
2357 * I have not found it yet. At this time we depend on the information
2358 * in the type info and the usual order how things are stored.
2360 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2363 * Third is an equal sized array with file offsets to the name entry
2366 * The fourth and last (?) part is an array with offsets to the records
2367 * in the first part of this file segment.
2370 int infolen
, nameoffset
, reclength
, i
;
2371 int recoffset
= offset
+ sizeof(INT
);
2373 char *recbuf
= heap_alloc(0xffff);
2374 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2375 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2377 TRACE_(typelib
)("\n");
2379 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2381 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2383 for ( i
= 0; i
< cFuncs
; i
++ )
2387 /* name, eventually add to a hash table */
2388 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2389 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2391 /* read the function information record */
2392 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2394 reclength
&= 0xffff;
2396 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2398 /* size without argument data */
2399 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2400 if (pFuncRec
->FKCCIC
& 0x1000)
2401 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2403 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2404 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2406 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2407 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2409 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2411 if (pFuncRec
->FKCCIC
& 0x2000 )
2413 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2414 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2415 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2418 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2421 ptfd
->Entry
= (TLBString
*)-1;
2423 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2424 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2426 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2427 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2429 /* fill the FuncDesc Structure */
2430 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2431 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2433 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2434 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2435 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2436 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2437 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2438 if (ptfd
->funcdesc
.funckind
== FUNC_DISPATCH
)
2439 ptfd
->funcdesc
.oVft
= 0;
2441 ptfd
->funcdesc
.oVft
= (pFuncRec
->VtableOffset
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
2442 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2444 /* nameoffset is sometimes -1 on the second half of a propget/propput
2445 * pair of functions */
2446 if ((nameoffset
== -1) && (i
> 0) &&
2447 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2448 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2449 ptfd
->Name
= ptfd_prev
->Name
;
2451 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2455 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2457 /* do the parameters/arguments */
2458 if(pFuncRec
->nrargs
)
2461 MSFT_ParameterInfo paraminfo
;
2463 ptfd
->funcdesc
.lprgelemdescParam
=
2464 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2466 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2468 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2469 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2471 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2473 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2479 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2482 if (paraminfo
.oName
!= -1)
2483 ptfd
->pParamDesc
[j
].Name
=
2484 MSFT_ReadName( pcx
, paraminfo
.oName
);
2485 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2488 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2489 (pFuncRec
->FKCCIC
& 0x1000) )
2491 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2493 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2495 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2497 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2498 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2500 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2504 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2507 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2508 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2509 pFuncRec
->FKCCIC
& 0x80 )
2512 pFuncRec
->oArgCustData
[j
],
2513 &ptfd
->pParamDesc
[j
].custdata_list
);
2516 /* SEEK value = jump to offset,
2517 * from there jump to the end of record,
2518 * go back by (j-1) arguments
2520 MSFT_ReadLEDWords( ¶minfo
,
2521 sizeof(MSFT_ParameterInfo
), pcx
,
2522 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2523 * sizeof(MSFT_ParameterInfo
)));
2527 /* scode is not used: archaic win16 stuff FIXME: right? */
2528 ptfd
->funcdesc
.cScodes
= 0 ;
2529 ptfd
->funcdesc
.lprgscode
= NULL
;
2533 recoffset
+= reclength
;
2538 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2539 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2541 int infolen
, nameoffset
, reclength
;
2543 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2548 TRACE_(typelib
)("\n");
2550 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2551 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2552 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2553 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2554 recoffset
+= offset
+sizeof(INT
);
2555 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2556 /* name, eventually add to a hash table */
2557 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2558 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2559 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2560 /* read the variable information record */
2561 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2563 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2566 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2567 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2569 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2570 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2572 if (reclength
> FIELD_OFFSET(MSFT_VarRecord
, oCustData
))
2573 MSFT_CustData(pcx
, pVarRec
->oCustData
, &ptvd
->custdata_list
);
2575 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2576 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2578 /* fill the VarDesc Structure */
2579 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2580 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2581 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2582 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2583 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2584 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2585 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2586 if(pVarRec
->VarKind
== VAR_CONST
){
2587 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2588 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2589 pVarRec
->OffsValue
, pcx
);
2591 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2592 recoffset
+= reclength
;
2596 /* process Implemented Interfaces of a com class */
2597 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2601 MSFT_RefRecord refrec
;
2604 TRACE_(typelib
)("\n");
2606 pTI
->impltypes
= TLBImplType_Alloc(count
);
2607 pImpl
= pTI
->impltypes
;
2608 for(i
=0;i
<count
;i
++){
2609 if(offset
<0) break; /* paranoia */
2610 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2611 pImpl
->hRef
= refrec
.reftype
;
2612 pImpl
->implflags
=refrec
.flags
;
2613 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2614 offset
=refrec
.onext
;
2620 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2621 * and some structures, and fix the alignment */
2622 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2624 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2625 switch(info
->tdescAlias
->vt
){
2633 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2634 info
->typeattr
.cbAlignment
= sizeof(void*);
2637 case VT_USERDEFINED
:
2638 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2641 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2642 info
->typeattr
.cbAlignment
= 8;
2644 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2645 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2647 info
->typeattr
.cbAlignment
= sizeof(void*);
2650 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2651 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2652 info
->typeattr
.typekind
== TKIND_COCLASS
){
2653 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2654 info
->typeattr
.cbAlignment
= sizeof(void*);
2660 * process a typeinfo record
2662 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2665 ITypeLibImpl
* pLibInfo
)
2667 MSFT_TypeInfoBase tiBase
;
2668 ITypeInfoImpl
*ptiRet
;
2670 TRACE_(typelib
)("count=%u\n", count
);
2672 ptiRet
= ITypeInfoImpl_Constructor();
2673 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2674 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2676 /* this is where we are coming from */
2677 ptiRet
->pTypeLib
= pLibInfo
;
2678 ptiRet
->index
=count
;
2680 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2681 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2682 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2683 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2684 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2685 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2686 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2687 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2688 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2689 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2690 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2691 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2692 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
;
2693 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2695 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2696 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2697 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2701 /* IDLDESC idldescType; *//* never saw this one != zero */
2703 /* name, eventually add to a hash table */
2704 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2705 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2706 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2708 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2709 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2710 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2712 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2713 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2715 /* note: InfoType's Help file and HelpStringDll come from the containing
2716 * library. Further HelpString and Docstring appear to be the same thing :(
2719 if(ptiRet
->typeattr
.cFuncs
>0 )
2720 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2721 ptiRet
->typeattr
.cVars
,
2722 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2724 if(ptiRet
->typeattr
.cVars
>0 )
2725 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2726 ptiRet
->typeattr
.cVars
,
2727 tiBase
.memoffset
, &ptiRet
->vardescs
);
2728 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2729 switch(ptiRet
->typeattr
.typekind
)
2732 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2735 case TKIND_DISPATCH
:
2736 /* This is not -1 when the interface is a non-base dual interface or
2737 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2738 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2742 if (tiBase
.datatype1
!= -1)
2744 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2745 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2749 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2750 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2754 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2756 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2757 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2758 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2759 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2760 if (TRACE_ON(typelib
))
2761 dump_TypeInfo(ptiRet
);
2766 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2769 INT16 len_str
, len_piece
;
2770 int offs
= 0, lengthInChars
;
2772 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2776 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2779 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2780 len_piece
= len_str
+ sizeof(INT16
);
2782 len_piece
= (len_piece
+ 4) & ~0x3;
2786 string
= heap_alloc(len_piece
+ 1);
2787 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2788 string
[len_str
] = '\0';
2790 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2791 string
, -1, NULL
, 0);
2792 if (!lengthInChars
) {
2794 return E_UNEXPECTED
;
2797 tlbstr
= heap_alloc(sizeof(TLBString
));
2799 tlbstr
->offset
= offs
;
2800 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2801 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2805 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2811 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2816 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2817 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2818 MSFT_ImpInfo impinfo
;
2821 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2823 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2824 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2826 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2827 if(pImpLib
->offset
==impinfo
.oImpFile
)
2830 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2831 ref
->reference
= offs
;
2832 ref
->pImpTLInfo
= pImpLib
;
2833 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2834 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2835 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2836 ref
->index
= TLB_REF_USE_GUID
;
2838 ref
->index
= impinfo
.oGuid
;
2840 ERR("Cannot find a reference\n");
2841 ref
->reference
= -1;
2842 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2845 offs
+= sizeof(impinfo
);
2851 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2852 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2853 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2856 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2857 static CRITICAL_SECTION cache_section
;
2858 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2860 0, 0, &cache_section
,
2861 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2862 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2864 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2867 typedef struct TLB_PEFile
2869 IUnknown IUnknown_iface
;
2872 HRSRC typelib_resource
;
2873 HGLOBAL typelib_global
;
2874 LPVOID typelib_base
;
2877 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2879 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2882 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2884 if (IsEqualIID(riid
, &IID_IUnknown
))
2887 IUnknown_AddRef(iface
);
2891 return E_NOINTERFACE
;
2894 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2896 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2897 return InterlockedIncrement(&This
->refs
);
2900 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2902 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2903 ULONG refs
= InterlockedDecrement(&This
->refs
);
2906 if (This
->typelib_global
)
2907 FreeResource(This
->typelib_global
);
2909 FreeLibrary(This
->dll
);
2915 static const IUnknownVtbl TLB_PEFile_Vtable
=
2917 TLB_PEFile_QueryInterface
,
2922 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2925 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2927 This
= heap_alloc(sizeof(TLB_PEFile
));
2929 return E_OUTOFMEMORY
;
2931 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2934 This
->typelib_resource
= NULL
;
2935 This
->typelib_global
= NULL
;
2936 This
->typelib_base
= NULL
;
2938 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2939 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2943 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), L
"TYPELIB");
2944 if (This
->typelib_resource
)
2946 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2947 if (This
->typelib_global
)
2949 This
->typelib_base
= LockResource(This
->typelib_global
);
2951 if (This
->typelib_base
)
2953 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2954 *ppBase
= This
->typelib_base
;
2955 *ppFile
= &This
->IUnknown_iface
;
2961 TRACE("No TYPELIB resource found\n");
2965 TLB_PEFile_Release(&This
->IUnknown_iface
);
2969 typedef struct TLB_NEFile
2971 IUnknown IUnknown_iface
;
2973 LPVOID typelib_base
;
2976 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2978 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2981 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2983 if (IsEqualIID(riid
, &IID_IUnknown
))
2986 IUnknown_AddRef(iface
);
2990 return E_NOINTERFACE
;
2993 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2995 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2996 return InterlockedIncrement(&This
->refs
);
2999 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
3001 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3002 ULONG refs
= InterlockedDecrement(&This
->refs
);
3005 heap_free(This
->typelib_base
);
3011 static const IUnknownVtbl TLB_NEFile_Vtable
=
3013 TLB_NEFile_QueryInterface
,
3018 /***********************************************************************
3019 * read_xx_header [internal]
3021 static int read_xx_header( HFILE lzfd
)
3023 IMAGE_DOS_HEADER mzh
;
3026 LZSeek( lzfd
, 0, SEEK_SET
);
3027 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3029 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3032 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3033 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3036 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3038 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3039 return IMAGE_OS2_SIGNATURE
;
3040 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3041 return IMAGE_NT_SIGNATURE
;
3044 WARN("Can't handle %s files.\n", magic
);
3049 /***********************************************************************
3050 * find_ne_resource [internal]
3052 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3053 DWORD
*resLen
, DWORD
*resOff
)
3055 IMAGE_OS2_HEADER nehd
;
3056 NE_TYPEINFO
*typeInfo
;
3057 NE_NAMEINFO
*nameInfo
;
3063 /* Read in NE header */
3064 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3065 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3067 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3070 TRACE("No resources in NE dll\n" );
3074 /* Read in resource table */
3075 resTab
= heap_alloc( resTabSize
);
3076 if ( !resTab
) return FALSE
;
3078 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3079 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3081 heap_free( resTab
);
3086 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3088 if (!IS_INTRESOURCE(typeid)) /* named type */
3090 BYTE len
= strlen( typeid );
3091 while (typeInfo
->type_id
)
3093 if (!(typeInfo
->type_id
& 0x8000))
3095 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3096 if ((*p
== len
) && !_strnicmp( (char*)p
+1, typeid, len
)) goto found_type
;
3098 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3099 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3102 else /* numeric type id */
3104 WORD id
= LOWORD(typeid) | 0x8000;
3105 while (typeInfo
->type_id
)
3107 if (typeInfo
->type_id
== id
) goto found_type
;
3108 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3109 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3112 TRACE("No typeid entry found for %p\n", typeid );
3113 heap_free( resTab
);
3117 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3119 if (!IS_INTRESOURCE(resid
)) /* named resource */
3121 BYTE len
= strlen( resid
);
3122 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3124 BYTE
*p
= resTab
+ nameInfo
->id
;
3125 if (nameInfo
->id
& 0x8000) continue;
3126 if ((*p
== len
) && !_strnicmp( (char*)p
+1, resid
, len
)) goto found_name
;
3129 else /* numeric resource id */
3131 WORD id
= LOWORD(resid
) | 0x8000;
3132 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3133 if (nameInfo
->id
== id
) goto found_name
;
3135 TRACE("No resid entry found for %p\n", typeid );
3136 heap_free( resTab
);
3140 /* Return resource data */
3141 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3142 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3144 heap_free( resTab
);
3148 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3152 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3155 This
= heap_alloc(sizeof(TLB_NEFile
));
3156 if (!This
) return E_OUTOFMEMORY
;
3158 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3160 This
->typelib_base
= NULL
;
3162 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3163 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3165 DWORD reslen
, offset
;
3166 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3168 This
->typelib_base
= heap_alloc(reslen
);
3169 if( !This
->typelib_base
)
3173 LZSeek( lzfd
, offset
, SEEK_SET
);
3174 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3176 *ppBase
= This
->typelib_base
;
3177 *pdwTLBLength
= reslen
;
3178 *ppFile
= &This
->IUnknown_iface
;
3184 if( lzfd
>= 0) LZClose( lzfd
);
3185 TLB_NEFile_Release(&This
->IUnknown_iface
);
3189 typedef struct TLB_Mapping
3191 IUnknown IUnknown_iface
;
3195 LPVOID typelib_base
;
3198 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3200 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3203 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3205 if (IsEqualIID(riid
, &IID_IUnknown
))
3208 IUnknown_AddRef(iface
);
3212 return E_NOINTERFACE
;
3215 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3217 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3218 return InterlockedIncrement(&This
->refs
);
3221 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3223 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3224 ULONG refs
= InterlockedDecrement(&This
->refs
);
3227 if (This
->typelib_base
)
3228 UnmapViewOfFile(This
->typelib_base
);
3230 CloseHandle(This
->mapping
);
3231 if (This
->file
!= INVALID_HANDLE_VALUE
)
3232 CloseHandle(This
->file
);
3238 static const IUnknownVtbl TLB_Mapping_Vtable
=
3240 TLB_Mapping_QueryInterface
,
3245 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3249 This
= heap_alloc(sizeof(TLB_Mapping
));
3251 return E_OUTOFMEMORY
;
3253 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3255 This
->file
= INVALID_HANDLE_VALUE
;
3256 This
->mapping
= NULL
;
3257 This
->typelib_base
= NULL
;
3259 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3260 if (INVALID_HANDLE_VALUE
!= This
->file
)
3262 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3265 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3266 if(This
->typelib_base
)
3268 /* retrieve file size */
3269 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3270 *ppBase
= This
->typelib_base
;
3271 *ppFile
= &This
->IUnknown_iface
;
3277 IUnknown_Release(&This
->IUnknown_iface
);
3278 return TYPE_E_CANTLOADLIBRARY
;
3281 /****************************************************************************
3284 * find the type of the typelib file and map the typelib resource into
3288 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3289 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3291 ITypeLibImpl
*entry
;
3294 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3295 LPVOID pBase
= NULL
;
3296 DWORD dwTLBLength
= 0;
3297 IUnknown
*pFile
= NULL
;
3302 index_str
= wcsrchr(pszFileName
, '\\');
3303 if(index_str
&& *++index_str
!= '\0')
3306 LONG idx
= wcstol(index_str
, &end_ptr
, 10);
3307 if(*end_ptr
== '\0')
3309 int str_len
= index_str
- pszFileName
- 1;
3311 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3312 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3317 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3319 if(wcschr(file
, '\\'))
3321 lstrcpyW(pszPath
, file
);
3325 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3326 pszPath
[len
] = '\\';
3327 memcpy(pszPath
+ len
+ 1, file
, (lstrlenW(file
) + 1) * sizeof(WCHAR
));
3331 if(file
!= pszFileName
) heap_free(file
);
3333 h
= CreateFileW(pszPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3334 if(h
!= INVALID_HANDLE_VALUE
){
3335 GetFinalPathNameByHandleW(h
, pszPath
, cchPath
, FILE_NAME_NORMALIZED
| VOLUME_NAME_DOS
);
3339 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3341 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3342 EnterCriticalSection(&cache_section
);
3343 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3345 if (!wcsicmp(entry
->path
, pszPath
) && entry
->index
== index
)
3347 TRACE("cache hit\n");
3348 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3349 ITypeLib2_AddRef(*ppTypeLib
);
3350 LeaveCriticalSection(&cache_section
);
3354 LeaveCriticalSection(&cache_section
);
3356 /* now actually load and parse the typelib */
3358 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3359 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3360 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3361 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3362 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3365 if (dwTLBLength
>= 4)
3367 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3368 if (dwSignature
== MSFT_SIGNATURE
)
3369 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3370 else if (dwSignature
== SLTG_SIGNATURE
)
3371 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3374 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3375 ret
= TYPE_E_CANTLOADLIBRARY
;
3379 ret
= TYPE_E_CANTLOADLIBRARY
;
3380 IUnknown_Release(pFile
);
3384 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3386 TRACE("adding to cache\n");
3387 impl
->path
= heap_alloc((lstrlenW(pszPath
)+1) * sizeof(WCHAR
));
3388 lstrcpyW(impl
->path
, pszPath
);
3389 /* We should really canonicalise the path here. */
3390 impl
->index
= index
;
3392 /* FIXME: check if it has added already in the meantime */
3393 EnterCriticalSection(&cache_section
);
3394 list_add_head(&tlb_cache
, &impl
->entry
);
3395 LeaveCriticalSection(&cache_section
);
3401 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3403 ret
= TYPE_E_CANTLOADLIBRARY
;
3410 /*================== ITypeLib(2) Methods ===================================*/
3412 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3414 ITypeLibImpl
* pTypeLibImpl
;
3416 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3417 if (!pTypeLibImpl
) return NULL
;
3419 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3420 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3421 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3422 pTypeLibImpl
->ref
= 1;
3424 list_init(&pTypeLibImpl
->implib_list
);
3425 list_init(&pTypeLibImpl
->custdata_list
);
3426 list_init(&pTypeLibImpl
->name_list
);
3427 list_init(&pTypeLibImpl
->string_list
);
3428 list_init(&pTypeLibImpl
->guid_list
);
3429 list_init(&pTypeLibImpl
->ref_list
);
3430 pTypeLibImpl
->dispatch_href
= -1;
3432 return pTypeLibImpl
;
3435 /****************************************************************************
3436 * ITypeLib2_Constructor_MSFT
3438 * loading an MSFT typelib from an in-memory image
3440 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3444 MSFT_Header tlbHeader
;
3445 MSFT_SegDir tlbSegDir
;
3446 ITypeLibImpl
* pTypeLibImpl
;
3449 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3451 pTypeLibImpl
= TypeLibImpl_Constructor();
3452 if (!pTypeLibImpl
) return NULL
;
3454 /* get pointer to beginning of typelib data */
3458 cx
.pLibInfo
= pTypeLibImpl
;
3459 cx
.length
= dwTLBLength
;
3462 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3463 TRACE_(typelib
)("header:\n");
3464 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3465 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3466 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3469 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3471 /* there is a small amount of information here until the next important
3473 * the segment directory . Try to calculate the amount of data */
3474 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3476 /* now read the segment directory */
3477 TRACE("read segment directory (at %d)\n",lPSegDir
);
3478 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3479 cx
.pTblDir
= &tlbSegDir
;
3481 /* just check two entries */
3482 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3484 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3485 heap_free(pTypeLibImpl
);
3489 MSFT_ReadAllNames(&cx
);
3490 MSFT_ReadAllStrings(&cx
);
3491 MSFT_ReadAllGuids(&cx
);
3493 /* now fill our internal data */
3494 /* TLIBATTR fields */
3495 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3497 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3498 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3499 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3500 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3501 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3503 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3504 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3506 /* name, eventually add to a hash table */
3507 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3510 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3511 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3513 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3516 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3517 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3520 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3523 if(tlbHeader
.CustomDataOffset
>= 0)
3525 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3528 /* fill in type descriptions */
3529 if(tlbSegDir
.pTypdescTab
.length
> 0)
3531 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3533 pTypeLibImpl
->ctTypeDesc
= cTD
;
3534 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3535 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3538 /* FIXME: add several sanity checks here */
3539 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3540 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3542 /* FIXME: check safearray */
3544 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3546 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3548 else if(td
[0] == VT_CARRAY
)
3550 /* array descr table here */
3551 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3553 else if(td
[0] == VT_USERDEFINED
)
3555 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3557 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3560 /* second time around to fill the array subscript info */
3563 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3564 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3566 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3567 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3570 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3572 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3574 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3576 for(j
= 0; j
<td
[2]; j
++)
3578 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3579 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3580 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3581 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3586 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3587 ERR("didn't find array description data\n");
3592 /* imported type libs */
3593 if(tlbSegDir
.pImpFiles
.offset
>0)
3596 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3599 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3603 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3604 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3605 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3607 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3608 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3609 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3610 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3613 name
= heap_alloc_zero(size
+1);
3614 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3615 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3618 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3619 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3621 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3625 MSFT_ReadAllRefs(&cx
);
3627 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3630 if(tlbHeader
.nrtypeinfos
>= 0 )
3632 ITypeInfoImpl
**ppTI
;
3634 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3636 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3638 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3641 (pTypeLibImpl
->TypeInfoCount
)++;
3646 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3647 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3648 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3652 TRACE("(%p)\n", pTypeLibImpl
);
3653 return &pTypeLibImpl
->ITypeLib2_iface
;
3657 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3663 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3664 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3668 guid
->Data4
[0] = s
>> 8;
3669 guid
->Data4
[1] = s
& 0xff;
3672 for(i
= 0; i
< 6; i
++) {
3673 memcpy(b
, str
+ 24 + 2 * i
, 2);
3674 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3679 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3686 bytelen
= *(const WORD
*)ptr
;
3687 if(bytelen
== 0xffff) return 2;
3689 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3690 tmp_str
= SysAllocStringLen(NULL
, len
);
3692 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3693 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3694 SysFreeString(tmp_str
);
3699 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3704 bytelen
= *(const WORD
*)ptr
;
3705 if(bytelen
== 0xffff) return 2;
3706 *str
= heap_alloc(bytelen
+ 1);
3707 memcpy(*str
, ptr
+ 2, bytelen
);
3708 (*str
)[bytelen
] = '\0';
3712 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3717 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3718 if (tlbstr
->offset
== offset
)
3722 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3723 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3724 SysFreeString(tmp_str
);
3729 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3731 char *ptr
= pLibBlk
;
3734 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3735 FIXME("libblk magic = %04x\n", w
);
3740 if((w
= *(WORD
*)ptr
) != 0xffff) {
3741 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w
);
3746 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3748 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3750 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3753 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3754 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3757 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3758 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3760 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3763 ptr
+= 4; /* skip res12 */
3765 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3768 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3771 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3774 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3775 ptr
+= sizeof(GUID
);
3777 return ptr
- (char*)pLibBlk
;
3780 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3785 } sltg_ref_lookup_t
;
3787 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3788 HREFTYPE
*typelib_ref
)
3790 if(table
&& typeinfo_ref
< table
->num
)
3792 *typelib_ref
= table
->refs
[typeinfo_ref
];
3796 ERR_(typelib
)("Unable to find reference\n");
3801 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3806 if((*pType
& 0xe00) == 0xe00) {
3808 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3809 pTD
= pTD
->u
.lptdesc
;
3811 switch(*pType
& 0x3f) {
3814 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3815 pTD
= pTD
->u
.lptdesc
;
3818 case VT_USERDEFINED
:
3819 pTD
->vt
= VT_USERDEFINED
;
3820 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3826 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3829 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3831 pTD
->vt
= VT_CARRAY
;
3832 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3833 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3834 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3835 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3837 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3843 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3847 pTD
->vt
= VT_SAFEARRAY
;
3848 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3849 pTD
= pTD
->u
.lptdesc
;
3853 pTD
->vt
= *pType
& 0x3f;
3862 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3863 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3865 /* Handle [in/out] first */
3866 if((*pType
& 0xc000) == 0xc000)
3867 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3868 else if(*pType
& 0x8000)
3869 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3870 else if(*pType
& 0x4000)
3871 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3873 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3876 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3879 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3881 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3885 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3890 TLBRefType
*ref_type
;
3891 sltg_ref_lookup_t
*table
;
3892 HREFTYPE typelib_ref
;
3894 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3895 FIXME("Ref magic = %x\n", pRef
->magic
);
3898 name
= ( (char*)pRef
->names
+ pRef
->number
);
3900 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3901 table
->num
= pRef
->number
>> 3;
3903 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3905 /* We don't want the first href to be 0 */
3906 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3908 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3910 unsigned int lib_offs
, type_num
;
3912 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3914 name
+= SLTG_ReadStringA(name
, &refname
);
3915 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3916 FIXME_(typelib
)("Can't sscanf ref\n");
3917 if(lib_offs
!= 0xffff) {
3920 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3921 if(import
->offset
== lib_offs
)
3924 if(&import
->entry
== &pTL
->implib_list
) {
3925 char fname
[MAX_PATH
+1];
3929 import
= heap_alloc_zero(sizeof(*import
));
3930 import
->offset
= lib_offs
;
3931 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3932 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3933 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3934 &import
->wVersionMajor
,
3935 &import
->wVersionMinor
,
3936 &import
->lcid
, fname
) != 4) {
3937 FIXME_(typelib
)("can't sscanf ref %s\n",
3938 pNameTable
+ lib_offs
+ 40);
3940 len
= strlen(fname
);
3941 if(fname
[len
-1] != '#')
3942 FIXME("fname = %s\n", fname
);
3943 fname
[len
-1] = '\0';
3944 import
->name
= TLB_MultiByteToBSTR(fname
);
3945 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3947 ref_type
->pImpTLInfo
= import
;
3949 /* Store a reference to IDispatch */
3950 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3951 pTL
->dispatch_href
= typelib_ref
;
3953 } else { /* internal ref */
3954 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3956 ref_type
->reference
= typelib_ref
;
3957 ref_type
->index
= type_num
;
3960 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3962 table
->refs
[ref
] = typelib_ref
;
3965 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3966 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3967 dump_TLBRefType(pTL
);
3971 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3972 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3974 SLTG_ImplInfo
*info
;
3975 TLBImplType
*pImplType
;
3976 /* I don't really get this structure, usually it's 0x16 bytes
3977 long, but iuser.tlb contains some that are 0x18 bytes long.
3978 That's ok because we can use the next ptr to jump to the next
3979 one. But how do we know the length of the last one? The WORD
3980 at offs 0x8 might be the clue. For now I'm just assuming that
3981 the last one is the regular 0x16 bytes. */
3983 info
= (SLTG_ImplInfo
*)pBlk
;
3985 pTI
->typeattr
.cImplTypes
++;
3986 if(info
->next
== 0xffff)
3988 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3991 info
= (SLTG_ImplInfo
*)pBlk
;
3992 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
3993 pImplType
= pTI
->impltypes
;
3995 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3996 pImplType
->implflags
= info
->impltypeflags
;
3999 if(info
->next
== 0xffff)
4002 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4003 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4005 info
++; /* see comment at top of function */
4009 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4010 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4012 TLBVarDesc
*pVarDesc
;
4013 const TLBString
*prevName
= NULL
;
4014 SLTG_Variable
*pItem
;
4018 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4020 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4021 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4023 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4025 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4026 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4027 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4031 if (pItem
->name
== 0xfffe)
4032 pVarDesc
->Name
= prevName
;
4034 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4036 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4037 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4038 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4040 if(pItem
->flags
& 0x02)
4041 pType
= &pItem
->type
;
4043 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4045 if (pItem
->flags
& ~0xda)
4046 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4048 SLTG_DoElem(pType
, pBlk
,
4049 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4051 if (TRACE_ON(typelib
)) {
4053 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4054 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4057 if (pItem
->flags
& 0x40) {
4058 TRACE_(typelib
)("VAR_DISPATCH\n");
4059 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4061 else if (pItem
->flags
& 0x10) {
4062 TRACE_(typelib
)("VAR_CONST\n");
4063 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4064 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4065 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4066 if (pItem
->flags
& 0x08)
4067 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4069 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4075 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4077 TRACE_(typelib
)("len = %u\n", len
);
4078 if (len
== 0xffff) {
4081 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4082 str
= SysAllocStringLen(NULL
, alloc_len
);
4083 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4085 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4086 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4095 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4096 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4099 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4104 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4105 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4106 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4109 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4110 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4112 if (pItem
->flags
& 0x80)
4113 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4115 prevName
= pVarDesc
->Name
;
4117 pTI
->typeattr
.cVars
= cVars
;
4120 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4121 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4123 SLTG_Function
*pFunc
;
4125 TLBFuncDesc
*pFuncDesc
;
4127 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4129 pFuncDesc
= pTI
->funcdescs
;
4130 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4131 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4136 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4137 case SLTG_FUNCTION_MAGIC
:
4138 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4140 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4141 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4143 case SLTG_STATIC_FUNCTION_MAGIC
:
4144 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4147 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4150 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4152 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4153 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4154 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4155 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4156 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4157 if (pFuncDesc
->funcdesc
.funckind
== FUNC_DISPATCH
)
4158 pFuncDesc
->funcdesc
.oVft
= 0;
4160 pFuncDesc
->funcdesc
.oVft
= (pFunc
->vtblpos
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
4162 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4163 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4165 if(pFunc
->retnextopt
& 0x80)
4166 pType
= &pFunc
->rettype
;
4168 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4170 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4172 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4173 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4174 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4176 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4178 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4179 char *paramName
= pNameTable
+ *pArg
;
4181 /* If arg type follows then paramName points to the 2nd
4182 letter of the name, else the next WORD is an offset to
4183 the arg type and paramName points to the first letter.
4184 So let's take one char off paramName and see if we're
4185 pointing at an alphanumeric char. However if *pArg is
4186 0xffff or 0xfffe then the param has no name, the former
4187 meaning that the next WORD is the type, the latter
4188 meaning that the next WORD is an offset to the type. */
4193 else if(*pArg
== 0xfffe) {
4197 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4202 if(HaveOffs
) { /* the next word is an offset to type */
4203 pType
= (WORD
*)(pBlk
+ *pArg
);
4204 SLTG_DoElem(pType
, pBlk
,
4205 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4210 pArg
= SLTG_DoElem(pArg
, pBlk
,
4211 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4214 /* Are we an optional param ? */
4215 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4216 pFuncDesc
->funcdesc
.cParamsOpt
)
4217 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4220 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4221 paramName
- pNameTable
, pTI
->pTypeLib
);
4223 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4227 pTI
->typeattr
.cFuncs
= cFuncs
;
4230 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4231 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4232 SLTG_TypeInfoTail
*pTITail
)
4235 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4237 if(pTIHeader
->href_table
!= 0xffffffff) {
4238 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4244 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4245 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4247 heap_free(ref_lookup
);
4251 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4252 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4253 const SLTG_TypeInfoTail
*pTITail
)
4256 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4258 if(pTIHeader
->href_table
!= 0xffffffff) {
4259 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4265 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4266 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4269 if (pTITail
->funcs_off
!= 0xffff)
4270 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4272 heap_free(ref_lookup
);
4274 if (TRACE_ON(typelib
))
4275 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4278 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4279 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4280 const SLTG_TypeInfoTail
*pTITail
)
4282 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4285 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4286 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4287 const SLTG_TypeInfoTail
*pTITail
)
4290 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4292 if (pTITail
->simple_alias
) {
4293 /* if simple alias, no more processing required */
4294 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4295 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4299 if(pTIHeader
->href_table
!= 0xffffffff) {
4300 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4304 /* otherwise it is an offset to a type */
4305 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4307 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4308 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4310 heap_free(ref_lookup
);
4313 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4314 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4315 const SLTG_TypeInfoTail
*pTITail
)
4317 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4318 if (pTIHeader
->href_table
!= 0xffffffff)
4319 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4322 if (pTITail
->vars_off
!= 0xffff)
4323 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4325 if (pTITail
->funcs_off
!= 0xffff)
4326 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4328 if (pTITail
->impls_off
!= 0xffff)
4329 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4331 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4332 * of dispinterface functions including the IDispatch ones, so
4333 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4334 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4336 heap_free(ref_lookup
);
4337 if (TRACE_ON(typelib
))
4338 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4341 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4342 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4343 const SLTG_TypeInfoTail
*pTITail
)
4345 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4348 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4349 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4350 const SLTG_TypeInfoTail
*pTITail
)
4352 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4353 if (pTIHeader
->href_table
!= 0xffffffff)
4354 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4357 if (pTITail
->vars_off
!= 0xffff)
4358 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4360 if (pTITail
->funcs_off
!= 0xffff)
4361 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4362 heap_free(ref_lookup
);
4363 if (TRACE_ON(typelib
))
4367 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4368 manageable copy of it into this */
4381 } SLTG_InternalOtherTypeInfo
;
4383 /****************************************************************************
4384 * ITypeLib2_Constructor_SLTG
4386 * loading a SLTG typelib from an in-memory image
4388 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4390 ITypeLibImpl
*pTypeLibImpl
;
4391 SLTG_Header
*pHeader
;
4392 SLTG_BlkEntry
*pBlkEntry
;
4396 LPVOID pBlk
, pFirstBlk
;
4397 SLTG_LibBlk
*pLibBlk
;
4398 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4399 char *pAfterOTIBlks
= NULL
;
4400 char *pNameTable
, *ptr
;
4403 ITypeInfoImpl
**ppTypeInfoImpl
;
4405 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4408 pTypeLibImpl
= TypeLibImpl_Constructor();
4409 if (!pTypeLibImpl
) return NULL
;
4413 TRACE_(typelib
)("header:\n");
4414 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4415 pHeader
->nrOfFileBlks
);
4416 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4417 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4418 pHeader
->SLTG_magic
);
4422 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4423 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4425 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4426 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4428 /* Next we have a magic block */
4429 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4431 /* Let's see if we're still in sync */
4432 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4433 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4434 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4437 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4438 sizeof(SLTG_DIR_MAGIC
))) {
4439 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4443 pIndex
= (SLTG_Index
*)(pMagic
+1);
4445 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4447 pFirstBlk
= pPad9
+ 1;
4449 /* We'll set up a ptr to the main library block, which is the last one. */
4451 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4452 pBlkEntry
[order
].next
!= 0;
4453 order
= pBlkEntry
[order
].next
- 1) {
4454 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4458 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4460 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4465 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4467 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4470 ptr
= (char*)pLibBlk
+ len
;
4472 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4476 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4478 w
= *(WORD
*)(ptr
+ 2);
4481 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4482 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4483 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4485 w
= *(WORD
*)(ptr
+ 4 + len
);
4487 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4489 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4490 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4491 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4493 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4494 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4495 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4497 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4498 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4501 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4502 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4503 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4504 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4505 len
+= sizeof(SLTG_OtherTypeInfo
);
4509 pAfterOTIBlks
= ptr
;
4511 /* Skip this WORD and get the next DWORD */
4512 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4514 /* Now add this to pLibBLk look at what we're pointing at and
4515 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4516 dust and we should be pointing at the beginning of the name
4519 pNameTable
= (char*)pLibBlk
+ len
;
4521 switch(*(WORD
*)pNameTable
) {
4528 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4532 pNameTable
+= 0x216;
4536 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4538 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4541 /* Hopefully we now have enough ptrs set up to actually read in
4542 some TypeInfos. It's not clear which order to do them in, so
4543 I'll just follow the links along the BlkEntry chain and read
4544 them in the order in which they are in the file */
4546 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4547 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4549 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4550 pBlkEntry
[order
].next
!= 0;
4551 order
= pBlkEntry
[order
].next
- 1, i
++) {
4553 SLTG_TypeInfoHeader
*pTIHeader
;
4554 SLTG_TypeInfoTail
*pTITail
;
4555 SLTG_MemberHeader
*pMemHeader
;
4557 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4558 FIXME_(typelib
)("Index strings don't match\n");
4559 heap_free(pOtherTypeInfoBlks
);
4564 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4565 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4566 heap_free(pOtherTypeInfoBlks
);
4569 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4570 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4571 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4573 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4574 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4575 (*ppTypeInfoImpl
)->index
= i
;
4576 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4577 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4578 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4579 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4580 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4581 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4582 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4583 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4585 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4586 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4588 if((pTIHeader
->typeflags1
& 7) != 2)
4589 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4590 if(pTIHeader
->typeflags3
!= 2)
4591 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4593 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4594 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4595 typekind_desc
[pTIHeader
->typekind
],
4596 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4597 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4599 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4601 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4603 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4604 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4605 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4607 switch(pTIHeader
->typekind
) {
4609 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4610 pTIHeader
, pTITail
);
4614 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4615 pTIHeader
, pTITail
);
4618 case TKIND_INTERFACE
:
4619 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4620 pTIHeader
, pTITail
);
4624 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4625 pTIHeader
, pTITail
);
4629 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4630 pTIHeader
, pTITail
);
4633 case TKIND_DISPATCH
:
4634 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4635 pTIHeader
, pTITail
);
4639 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4640 pTIHeader
, pTITail
);
4644 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4649 /* could get cFuncs, cVars and cImplTypes from here
4650 but we've already set those */
4651 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4667 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4670 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4671 FIXME("Somehow processed %d TypeInfos\n", i
);
4672 heap_free(pOtherTypeInfoBlks
);
4676 heap_free(pOtherTypeInfoBlks
);
4677 return &pTypeLibImpl
->ITypeLib2_iface
;
4680 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4682 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4684 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4686 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4687 IsEqualIID(riid
,&IID_ITypeLib
)||
4688 IsEqualIID(riid
,&IID_ITypeLib2
))
4690 *ppv
= &This
->ITypeLib2_iface
;
4692 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4693 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4695 *ppv
= &This
->ICreateTypeLib2_iface
;
4700 TRACE("-- Interface: E_NOINTERFACE\n");
4701 return E_NOINTERFACE
;
4704 IUnknown_AddRef((IUnknown
*)*ppv
);
4708 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4710 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4711 ULONG ref
= InterlockedIncrement(&This
->ref
);
4713 TRACE("(%p) ref=%u\n", This
, ref
);
4718 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4720 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4721 ULONG ref
= InterlockedDecrement(&This
->ref
);
4723 TRACE("(%p) ref=%u\n",This
, ref
);
4727 TLBImpLib
*pImpLib
, *pImpLibNext
;
4728 TLBRefType
*ref_type
, *ref_type_next
;
4729 TLBString
*tlbstr
, *tlbstr_next
;
4730 TLBGuid
*tlbguid
, *tlbguid_next
;
4733 /* remove cache entry */
4736 TRACE("removing from cache list\n");
4737 EnterCriticalSection(&cache_section
);
4738 if(This
->entry
.next
)
4739 list_remove(&This
->entry
);
4740 LeaveCriticalSection(&cache_section
);
4741 heap_free(This
->path
);
4743 TRACE(" destroying ITypeLib(%p)\n",This
);
4745 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4746 list_remove(&tlbstr
->entry
);
4747 SysFreeString(tlbstr
->str
);
4751 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4752 list_remove(&tlbstr
->entry
);
4753 SysFreeString(tlbstr
->str
);
4757 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4758 list_remove(&tlbguid
->entry
);
4762 TLB_FreeCustData(&This
->custdata_list
);
4764 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4765 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4766 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4768 heap_free(This
->pTypeDesc
);
4770 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4772 if (pImpLib
->pImpTypeLib
)
4773 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4774 SysFreeString(pImpLib
->name
);
4776 list_remove(&pImpLib
->entry
);
4780 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, ref_type_next
, &This
->ref_list
, TLBRefType
, entry
)
4782 list_remove(&ref_type
->entry
);
4783 heap_free(ref_type
);
4786 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4787 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4788 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4790 heap_free(This
->typeinfos
);
4798 /* ITypeLib::GetTypeInfoCount
4800 * Returns the number of type descriptions in the type library
4802 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4804 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4805 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4806 return This
->TypeInfoCount
;
4809 /* ITypeLib::GetTypeInfo
4811 * retrieves the specified type description in the library.
4813 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4816 ITypeInfo
**ppTInfo
)
4818 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4820 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4823 return E_INVALIDARG
;
4825 if(index
>= This
->TypeInfoCount
)
4826 return TYPE_E_ELEMENTNOTFOUND
;
4828 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4829 ITypeInfo_AddRef(*ppTInfo
);
4835 /* ITypeLibs::GetTypeInfoType
4837 * Retrieves the type of a type description.
4839 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4844 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4846 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4849 return E_INVALIDARG
;
4851 if(index
>= This
->TypeInfoCount
)
4852 return TYPE_E_ELEMENTNOTFOUND
;
4854 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4859 /* ITypeLib::GetTypeInfoOfGuid
4861 * Retrieves the type description that corresponds to the specified GUID.
4864 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4867 ITypeInfo
**ppTInfo
)
4869 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4872 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4874 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4875 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4876 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4877 ITypeInfo_AddRef(*ppTInfo
);
4882 return TYPE_E_ELEMENTNOTFOUND
;
4885 /* ITypeLib::GetLibAttr
4887 * Retrieves the structure that contains the library's attributes.
4890 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4894 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4896 TRACE("(%p, %p)\n", This
, attr
);
4898 if (!attr
) return E_INVALIDARG
;
4900 *attr
= heap_alloc(sizeof(**attr
));
4901 if (!*attr
) return E_OUTOFMEMORY
;
4903 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4904 (*attr
)->lcid
= This
->set_lcid
;
4905 (*attr
)->syskind
= This
->syskind
;
4906 (*attr
)->wMajorVerNum
= This
->ver_major
;
4907 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4908 (*attr
)->wLibFlags
= This
->libflags
;
4913 /* ITypeLib::GetTypeComp
4915 * Enables a client compiler to bind to a library's types, variables,
4916 * constants, and global functions.
4919 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4921 ITypeComp
**ppTComp
)
4923 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4925 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4926 *ppTComp
= &This
->ITypeComp_iface
;
4927 ITypeComp_AddRef(*ppTComp
);
4932 /* ITypeLib::GetDocumentation
4934 * Retrieves the library's documentation string, the complete Help file name
4935 * and path, and the context identifier for the library Help topic in the Help
4938 * On a successful return all non-null BSTR pointers will have been set,
4941 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4945 BSTR
*pBstrDocString
,
4946 DWORD
*pdwHelpContext
,
4947 BSTR
*pBstrHelpFile
)
4949 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4950 HRESULT result
= E_INVALIDARG
;
4953 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4955 pBstrName
, pBstrDocString
,
4956 pdwHelpContext
, pBstrHelpFile
);
4960 /* documentation for the typelib */
4965 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4973 if (This
->DocString
)
4975 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4979 *pBstrDocString
= NULL
;
4983 *pdwHelpContext
= This
->dwHelpContext
;
4989 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
4993 *pBstrHelpFile
= NULL
;
5000 /* for a typeinfo */
5001 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5003 if(SUCCEEDED(result
))
5005 result
= ITypeInfo_GetDocumentation(pTInfo
,
5009 pdwHelpContext
, pBstrHelpFile
);
5011 ITypeInfo_Release(pTInfo
);
5016 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5018 if (pBstrName
) SysFreeString (*pBstrName
);
5020 return STG_E_INSUFFICIENTMEMORY
;
5025 * Indicates whether a passed-in string contains the name of a type or member
5026 * described in the library.
5029 static HRESULT WINAPI
ITypeLib2_fnIsName(
5035 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5037 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5039 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5043 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5044 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5045 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5046 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5047 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5049 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5050 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5051 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5052 goto ITypeLib2_fnIsName_exit
;
5055 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5056 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5057 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5063 ITypeLib2_fnIsName_exit
:
5064 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5065 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5070 /* ITypeLib::FindName
5072 * Finds occurrences of a type description in a type library. This may be used
5073 * to quickly verify that a name exists in a type library.
5076 static HRESULT WINAPI
ITypeLib2_fnFindName(
5080 ITypeInfo
**ppTInfo
,
5084 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5089 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5091 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5092 return E_INVALIDARG
;
5094 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5095 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5096 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5100 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5101 memid
[count
] = MEMBERID_NIL
;
5102 goto ITypeLib2_fnFindName_exit
;
5105 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5106 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5108 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5109 memid
[count
] = func
->funcdesc
.memid
;
5110 goto ITypeLib2_fnFindName_exit
;
5114 var
= TLB_get_vardesc_by_name(pTInfo
, name
);
5116 memid
[count
] = var
->vardesc
.memid
;
5117 goto ITypeLib2_fnFindName_exit
;
5121 ITypeLib2_fnFindName_exit
:
5122 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5123 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5126 TRACE("found %d typeinfos\n", count
);
5133 /* ITypeLib::ReleaseTLibAttr
5135 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5138 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5140 TLIBATTR
*pTLibAttr
)
5142 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5143 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5144 heap_free(pTLibAttr
);
5147 /* ITypeLib2::GetCustData
5149 * gets the custom data
5151 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5156 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5157 TLBCustData
*pCData
;
5159 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5161 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5163 return TYPE_E_ELEMENTNOTFOUND
;
5165 VariantInit(pVarVal
);
5166 VariantCopy(pVarVal
, &pCData
->data
);
5171 /* ITypeLib2::GetLibStatistics
5173 * Returns statistics about a type library that are required for efficient
5174 * sizing of hash tables.
5177 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5179 ULONG
*pcUniqueNames
,
5180 ULONG
*pcchUniqueNames
)
5182 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5184 FIXME("(%p): stub!\n", This
);
5186 if(pcUniqueNames
) *pcUniqueNames
=1;
5187 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5191 /* ITypeLib2::GetDocumentation2
5193 * Retrieves the library's documentation string, the complete Help file name
5194 * and path, the localization context to use, and the context ID for the
5195 * library Help topic in the Help file.
5198 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5202 BSTR
*pbstrHelpString
,
5203 DWORD
*pdwHelpStringContext
,
5204 BSTR
*pbstrHelpStringDll
)
5206 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5210 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5212 /* the help string should be obtained from the helpstringdll,
5213 * using the _DLLGetDocumentation function, based on the supplied
5214 * lcid. Nice to do sometime...
5218 /* documentation for the typelib */
5220 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5221 if(pdwHelpStringContext
)
5222 *pdwHelpStringContext
=This
->dwHelpContext
;
5223 if(pbstrHelpStringDll
)
5224 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5230 /* for a typeinfo */
5231 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5233 if(SUCCEEDED(result
))
5235 ITypeInfo2
* pTInfo2
;
5236 result
= ITypeInfo_QueryInterface(pTInfo
,
5238 (LPVOID
*) &pTInfo2
);
5240 if(SUCCEEDED(result
))
5242 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5246 pdwHelpStringContext
,
5247 pbstrHelpStringDll
);
5249 ITypeInfo2_Release(pTInfo2
);
5252 ITypeInfo_Release(pTInfo
);
5258 static HRESULT
TLB_copy_all_custdata(const struct list
*custdata_list
, CUSTDATA
*pCustData
)
5260 TLBCustData
*pCData
;
5265 ct
= list_count(custdata_list
);
5267 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5268 if(!pCustData
->prgCustData
)
5269 return E_OUTOFMEMORY
;
5271 pCustData
->cCustData
= ct
;
5273 cdi
= pCustData
->prgCustData
;
5274 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5275 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5276 VariantInit(&cdi
->varValue
);
5277 hr
= VariantCopy(&cdi
->varValue
, &pCData
->data
);
5278 if(FAILED(hr
)) break;
5286 /* ITypeLib2::GetAllCustData
5288 * Gets all custom data items for the library.
5291 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5293 CUSTDATA
*pCustData
)
5295 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5296 TRACE("(%p)->(%p)\n", This
, pCustData
);
5297 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5300 static const ITypeLib2Vtbl tlbvt
= {
5301 ITypeLib2_fnQueryInterface
,
5303 ITypeLib2_fnRelease
,
5304 ITypeLib2_fnGetTypeInfoCount
,
5305 ITypeLib2_fnGetTypeInfo
,
5306 ITypeLib2_fnGetTypeInfoType
,
5307 ITypeLib2_fnGetTypeInfoOfGuid
,
5308 ITypeLib2_fnGetLibAttr
,
5309 ITypeLib2_fnGetTypeComp
,
5310 ITypeLib2_fnGetDocumentation
,
5312 ITypeLib2_fnFindName
,
5313 ITypeLib2_fnReleaseTLibAttr
,
5315 ITypeLib2_fnGetCustData
,
5316 ITypeLib2_fnGetLibStatistics
,
5317 ITypeLib2_fnGetDocumentation2
,
5318 ITypeLib2_fnGetAllCustData
5322 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5324 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5326 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5329 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5331 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5333 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5336 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5338 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5340 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5343 static HRESULT WINAPI
ITypeLibComp_fnBind(
5348 ITypeInfo
** ppTInfo
,
5349 DESCKIND
* pDescKind
,
5352 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5353 BOOL typemismatch
= FALSE
;
5356 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5358 *pDescKind
= DESCKIND_NONE
;
5359 pBindPtr
->lptcomp
= NULL
;
5362 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5363 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5364 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5366 /* FIXME: check wFlags here? */
5367 /* FIXME: we should use a hash table to look this info up using lHash
5368 * instead of an O(n) search */
5369 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5370 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5372 if (pTypeInfo
->Name
&& !wcscmp(pTypeInfo
->Name
->str
, szName
))
5374 *pDescKind
= DESCKIND_TYPECOMP
;
5375 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5376 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5377 TRACE("module or enum: %s\n", debugstr_w(szName
));
5382 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5383 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5385 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5388 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5389 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5391 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5394 else if (hr
== TYPE_E_TYPEMISMATCH
)
5395 typemismatch
= TRUE
;
5398 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5399 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5401 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5403 ITypeInfo
*subtypeinfo
;
5405 DESCKIND subdesckind
;
5407 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5408 &subtypeinfo
, &subdesckind
, &subbindptr
);
5409 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5411 TYPEDESC tdesc_appobject
;
5412 const VARDESC vardesc_appobject
=
5415 NULL
, /* lpstrSchema */
5430 VAR_STATIC
/* varkind */
5433 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5434 tdesc_appobject
.vt
= VT_USERDEFINED
;
5436 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5438 /* cleanup things filled in by Bind call so we can put our
5439 * application object data in there instead */
5440 switch (subdesckind
)
5442 case DESCKIND_FUNCDESC
:
5443 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5445 case DESCKIND_VARDESC
:
5446 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5451 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5453 if (pTypeInfo
->hreftype
== -1)
5454 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5456 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5460 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5461 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5462 ITypeInfo_AddRef(*ppTInfo
);
5465 else if (hr
== TYPE_E_TYPEMISMATCH
)
5466 typemismatch
= TRUE
;
5472 TRACE("type mismatch %s\n", debugstr_w(szName
));
5473 return TYPE_E_TYPEMISMATCH
;
5477 TRACE("name not found %s\n", debugstr_w(szName
));
5482 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5486 ITypeInfo
** ppTInfo
,
5487 ITypeComp
** ppTComp
)
5489 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5490 ITypeInfoImpl
*info
;
5492 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5494 if(!szName
|| !ppTInfo
|| !ppTComp
)
5495 return E_INVALIDARG
;
5497 info
= TLB_get_typeinfo_by_name(This
, szName
);
5504 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5505 ITypeInfo_AddRef(*ppTInfo
);
5506 *ppTComp
= &info
->ITypeComp_iface
;
5507 ITypeComp_AddRef(*ppTComp
);
5512 static const ITypeCompVtbl tlbtcvt
=
5515 ITypeLibComp_fnQueryInterface
,
5516 ITypeLibComp_fnAddRef
,
5517 ITypeLibComp_fnRelease
,
5519 ITypeLibComp_fnBind
,
5520 ITypeLibComp_fnBindType
5523 /*================== ITypeInfo(2) Methods ===================================*/
5524 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5526 ITypeInfoImpl
*pTypeInfoImpl
;
5528 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5531 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5532 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5533 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5534 pTypeInfoImpl
->ref
= 0;
5535 pTypeInfoImpl
->hreftype
= -1;
5536 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5537 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5538 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5539 list_init(pTypeInfoImpl
->pcustdata_list
);
5541 TRACE("(%p)\n", pTypeInfoImpl
);
5542 return pTypeInfoImpl
;
5545 /* ITypeInfo::QueryInterface
5547 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5552 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5554 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5557 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5558 IsEqualIID(riid
,&IID_ITypeInfo
)||
5559 IsEqualIID(riid
,&IID_ITypeInfo2
))
5560 *ppvObject
= &This
->ITypeInfo2_iface
;
5561 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5562 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5563 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5564 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5565 *ppvObject
= &This
->ITypeComp_iface
;
5568 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5569 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5572 TRACE("-- Interface: E_NOINTERFACE\n");
5573 return E_NOINTERFACE
;
5576 /* ITypeInfo::AddRef
5578 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5580 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5581 ULONG ref
= InterlockedIncrement(&This
->ref
);
5583 TRACE("(%p)->ref is %u\n",This
, ref
);
5585 if (ref
== 1 /* incremented from 0 */)
5586 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5591 static void typeinfo_release_funcdesc(TLBFuncDesc
*func
)
5595 for (i
= 0; i
< func
->funcdesc
.cParams
; ++i
)
5597 ELEMDESC
*elemdesc
= &func
->funcdesc
.lprgelemdescParam
[i
];
5598 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5599 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5600 TLB_FreeCustData(&func
->pParamDesc
[i
].custdata_list
);
5602 heap_free(func
->funcdesc
.lprgelemdescParam
);
5603 heap_free(func
->pParamDesc
);
5604 TLB_FreeCustData(&func
->custdata_list
);
5607 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5611 TRACE("destroying ITypeInfo(%p)\n",This
);
5613 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5615 typeinfo_release_funcdesc(&This
->funcdescs
[i
]);
5617 heap_free(This
->funcdescs
);
5619 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5621 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5622 if (pVInfo
->vardesc_create
) {
5623 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5624 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5625 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5626 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5628 TLB_FreeCustData(&pVInfo
->custdata_list
);
5630 heap_free(This
->vardescs
);
5632 if(This
->impltypes
){
5633 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5634 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5635 TLB_FreeCustData(&pImpl
->custdata_list
);
5637 heap_free(This
->impltypes
);
5640 TLB_FreeCustData(&This
->custdata_list
);
5645 /* ITypeInfo::Release
5647 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5649 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5650 ULONG ref
= InterlockedDecrement(&This
->ref
);
5652 TRACE("(%p)->(%u)\n",This
, ref
);
5656 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5657 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5658 if (not_attached_to_typelib
)
5660 /* otherwise This will be freed when typelib is freed */
5666 /* ITypeInfo::GetTypeAttr
5668 * Retrieves a TYPEATTR structure that contains the attributes of the type
5672 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5673 LPTYPEATTR
*ppTypeAttr
)
5675 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5678 TRACE("(%p)\n",This
);
5680 size
= sizeof(**ppTypeAttr
);
5681 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5682 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5684 *ppTypeAttr
= heap_alloc(size
);
5686 return E_OUTOFMEMORY
;
5688 **ppTypeAttr
= This
->typeattr
;
5689 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5691 if (This
->tdescAlias
)
5692 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5694 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5695 /* This should include all the inherited funcs */
5696 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5697 /* This is always the size of IDispatch's vtbl */
5698 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5699 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5704 /* ITypeInfo::GetTypeComp
5706 * Retrieves the ITypeComp interface for the type description, which enables a
5707 * client compiler to bind to the type description's members.
5710 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5711 ITypeComp
* *ppTComp
)
5713 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5715 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5717 *ppTComp
= &This
->ITypeComp_iface
;
5718 ITypeComp_AddRef(*ppTComp
);
5722 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5724 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5725 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5726 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5730 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5733 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5734 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5736 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5737 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5738 *buffer
+= sizeof(PARAMDESCEX
);
5739 *pparamdescex_dest
= *pparamdescex_src
;
5740 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5741 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5742 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5743 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5746 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5750 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5752 UINT len
= SysStringLen(str
), i
;
5753 for (i
= 0; i
< len
; ++i
)
5759 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5761 if (V_VT(var
) == VT_INT
)
5762 return VariantChangeType(var
, var
, 0, VT_I4
);
5763 else if (V_VT(var
) == VT_UINT
)
5764 return VariantChangeType(var
, var
, 0, VT_UI4
);
5765 else if (V_VT(var
) == VT_BSTR
)
5766 return TLB_SanitizeBSTR(V_BSTR(var
));
5771 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5773 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5774 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5777 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5781 SIZE_T size
= sizeof(*src
);
5785 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5786 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5787 for (i
= 0; i
< src
->cParams
; i
++)
5789 size
+= sizeof(ELEMDESC
);
5790 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5793 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5794 if (!dest
) return E_OUTOFMEMORY
;
5797 if (dispinterface
) /* overwrite funckind */
5798 dest
->funckind
= FUNC_DISPATCH
;
5799 buffer
= (char *)(dest
+ 1);
5801 dest
->oVft
= dest
->oVft
& 0xFFFC;
5803 if (dest
->cScodes
) {
5804 dest
->lprgscode
= (SCODE
*)buffer
;
5805 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5806 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5808 dest
->lprgscode
= NULL
;
5810 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5813 SysFreeString((BSTR
)dest
);
5817 if (dest
->cParams
) {
5818 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5819 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5820 for (i
= 0; i
< src
->cParams
; i
++)
5822 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5828 /* undo the above actions */
5829 for (i
= i
- 1; i
>= 0; i
--)
5830 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5831 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5832 SysFreeString((BSTR
)dest
);
5836 dest
->lprgelemdescParam
= NULL
;
5838 /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
5839 * This accounts for several arguments that are separate in the signature of
5840 * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
5841 if (dispinterface
&& (src
->funckind
!= FUNC_DISPATCH
))
5843 /* functions that have a [retval] parameter return this value into pVarResult.
5844 * [retval] is always the last parameter (if present) */
5845 if (dest
->cParams
&&
5846 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5848 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5849 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5851 ERR("elemdesc should have started with VT_PTR instead of:\n");
5853 dump_ELEMDESC(elemdesc
);
5854 return E_UNEXPECTED
;
5857 /* the type pointed to by this [retval] becomes elemdescFunc,
5858 * i.e. the function signature's return type.
5859 * We are using a flat buffer so there is no danger of leaking memory */
5860 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5862 /* remove the last parameter */
5865 else if (dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5866 /* Even if not otherwise replaced HRESULT is returned in pExcepInfo->scode,
5867 * not pVarResult. So the function signature should show no return value. */
5868 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5870 /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
5871 * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
5872 if (dest
->cParams
&& (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FLCID
))
5880 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5882 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5883 if (var_desc
->varkind
== VAR_CONST
)
5884 VariantClear(var_desc
->u
.lpvarValue
);
5885 SysFreeString((BSTR
)var_desc
);
5888 /* internal function to make the inherited interfaces' methods appear
5889 * part of the interface */
5890 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5891 UINT index
, const TLBFuncDesc
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5893 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5895 UINT implemented_funcs
= 0;
5900 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5904 ITypeInfo
*pSubTypeInfo
;
5907 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5911 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5914 &sub_funcs
, hrefoffset
);
5915 implemented_funcs
+= sub_funcs
;
5916 ITypeInfo_Release(pSubTypeInfo
);
5919 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5923 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5927 if (index
< implemented_funcs
)
5928 return E_INVALIDARG
;
5929 index
-= implemented_funcs
;
5931 if (index
>= This
->typeattr
.cFuncs
)
5932 return TYPE_E_ELEMENTNOTFOUND
;
5934 *ppFuncDesc
= &This
->funcdescs
[index
];
5938 static HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const TLBFuncDesc
**func_desc
, UINT
*hrefoffset
)
5940 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5942 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5943 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface
, index
, func_desc
, NULL
, hrefoffset
);
5945 if (index
>= This
->typeattr
.cFuncs
)
5946 return TYPE_E_ELEMENTNOTFOUND
;
5948 *func_desc
= &This
->funcdescs
[index
];
5952 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5954 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5957 switch (pTypeDesc
->vt
)
5959 case VT_USERDEFINED
:
5960 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5964 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5967 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5975 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5978 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5979 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5980 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5983 /* ITypeInfo::GetFuncDesc
5985 * Retrieves the FUNCDESC structure that contains information about a
5986 * specified function.
5989 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5990 LPFUNCDESC
*ppFuncDesc
)
5992 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5993 const TLBFuncDesc
*internal_funcdesc
;
5995 UINT hrefoffset
= 0;
5997 TRACE("(%p) index %d\n", This
, index
);
6000 return E_INVALIDARG
;
6002 if (This
->needs_layout
)
6003 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6005 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6006 &internal_funcdesc
, &hrefoffset
);
6009 WARN("description for function %d not found\n", index
);
6013 hr
= TLB_AllocAndInitFuncDesc(
6014 &internal_funcdesc
->funcdesc
,
6016 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6018 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
6019 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6021 TRACE("-- 0x%08x\n", hr
);
6025 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6029 SIZE_T size
= sizeof(*src
);
6032 if (src
->lpstrSchema
) size
+= (lstrlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6033 if (src
->varkind
== VAR_CONST
)
6034 size
+= sizeof(VARIANT
);
6035 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6037 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6038 if (!dest
) return E_OUTOFMEMORY
;
6041 buffer
= (char *)(dest
+ 1);
6042 if (src
->lpstrSchema
)
6045 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6046 len
= lstrlenW(src
->lpstrSchema
);
6047 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6048 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6051 if (src
->varkind
== VAR_CONST
)
6055 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6056 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6057 buffer
+= sizeof(VARIANT
);
6058 VariantInit(dest
->u
.lpvarValue
);
6059 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6062 SysFreeString((BSTR
)dest
);
6066 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6069 if (src
->varkind
== VAR_CONST
)
6070 VariantClear(dest
->u
.lpvarValue
);
6071 SysFreeString((BSTR
)dest
);
6078 /* ITypeInfo::GetVarDesc
6080 * Retrieves a VARDESC structure that describes the specified variable.
6083 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6084 LPVARDESC
*ppVarDesc
)
6086 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6087 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6089 TRACE("(%p) index %d\n", This
, index
);
6091 if(index
>= This
->typeattr
.cVars
)
6092 return TYPE_E_ELEMENTNOTFOUND
;
6094 if (This
->needs_layout
)
6095 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6097 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6100 /* internal function to make the inherited interfaces' methods appear
6101 * part of the interface, remembering if the top-level was dispinterface */
6102 static HRESULT
typeinfo_getnames( ITypeInfo
*iface
, MEMBERID memid
, BSTR
*names
,
6103 UINT max_names
, UINT
*num_names
, BOOL dispinterface
)
6105 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
6106 const TLBFuncDesc
*func_desc
;
6107 const TLBVarDesc
*var_desc
;
6112 func_desc
= TLB_get_funcdesc_by_memberid(This
, memid
);
6115 UINT params
= func_desc
->funcdesc
.cParams
;
6116 if (!max_names
|| !func_desc
->Name
)
6119 *names
= SysAllocString(TLB_get_bstr(func_desc
->Name
));
6122 if (dispinterface
&& (func_desc
->funcdesc
.funckind
!= FUNC_DISPATCH
))
6124 /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc */
6125 if ((params
> 0) && (func_desc
->funcdesc
.lprgelemdescParam
[params
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
6126 --params
; /* Invoke(pVarResult) supplies the [retval] parameter, so it's hidden from DISPPARAMS */
6127 if ((params
> 0) && (func_desc
->funcdesc
.lprgelemdescParam
[params
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FLCID
))
6128 --params
; /* Invoke(lcid) supplies the [lcid] parameter, so it's hidden from DISPPARAMS */
6131 for (i
= 0; i
< params
; i
++)
6133 if (*num_names
>= max_names
|| !func_desc
->pParamDesc
[i
].Name
)
6135 names
[*num_names
] = SysAllocString(TLB_get_bstr(func_desc
->pParamDesc
[i
].Name
));
6141 var_desc
= TLB_get_vardesc_by_memberid(This
, memid
);
6144 *names
= SysAllocString(TLB_get_bstr(var_desc
->Name
));
6149 if (This
->impltypes
&&
6150 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
))
6152 /* recursive search */
6155 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &parent
);
6156 if (SUCCEEDED(result
))
6158 result
= typeinfo_getnames(parent
, memid
, names
, max_names
, num_names
, dispinterface
);
6159 ITypeInfo_Release(parent
);
6162 WARN("Could not search inherited interface!\n");
6166 WARN("no names found\n");
6169 return TYPE_E_ELEMENTNOTFOUND
;
6174 /* ITypeInfo_GetNames
6176 * Retrieves the variable with the specified member ID (or the name of the
6177 * property or method and its parameters) that correspond to the specified
6180 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6181 BSTR
*names
, UINT max_names
, UINT
*num_names
)
6183 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6185 TRACE("(%p) memid 0x%08x max_names %d\n", This
, memid
, max_names
);
6187 if (!names
) return E_INVALIDARG
;
6189 return typeinfo_getnames((ITypeInfo
*)iface
, memid
, names
, max_names
, num_names
,
6190 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6193 /* ITypeInfo::GetRefTypeOfImplType
6195 * If a type description describes a COM class, it retrieves the type
6196 * description of the implemented interface types. For an interface,
6197 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6201 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6206 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6209 TRACE("(%p) index %d\n", This
, index
);
6210 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6214 /* only valid on dual interfaces;
6215 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6218 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6224 hr
= TYPE_E_ELEMENTNOTFOUND
;
6227 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6229 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6230 *pRefType
= This
->pTypeLib
->dispatch_href
;
6234 if(index
>= This
->typeattr
.cImplTypes
)
6235 hr
= TYPE_E_ELEMENTNOTFOUND
;
6237 *pRefType
= This
->impltypes
[index
].hRef
;
6238 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6246 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6248 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6254 /* ITypeInfo::GetImplTypeFlags
6256 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6257 * or base interface in a type description.
6259 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6260 UINT index
, INT
*pImplTypeFlags
)
6262 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6264 TRACE("(%p) index %d\n", This
, index
);
6267 return E_INVALIDARG
;
6269 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6270 *pImplTypeFlags
= 0;
6274 if(index
>= This
->typeattr
.cImplTypes
)
6275 return TYPE_E_ELEMENTNOTFOUND
;
6277 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6283 * Maps between member names and member IDs, and parameter names and
6286 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6287 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6289 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6290 const TLBVarDesc
*pVDesc
;
6294 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6297 /* init out parameters in case of failure */
6298 for (i
= 0; i
< cNames
; i
++)
6299 pMemId
[i
] = MEMBERID_NIL
;
6301 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6303 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6304 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6305 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6306 for(i
=1; i
< cNames
; i
++){
6307 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6308 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6310 if( j
<pFDesc
->funcdesc
.cParams
)
6313 ret
=DISP_E_UNKNOWNNAME
;
6315 TRACE("-- 0x%08x\n", ret
);
6319 pVDesc
= TLB_get_vardesc_by_name(This
, *rgszNames
);
6322 *pMemId
= pVDesc
->vardesc
.memid
;
6325 /* not found, see if it can be found in an inherited interface */
6326 if(This
->impltypes
) {
6327 /* recursive search */
6329 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6331 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6332 ITypeInfo_Release(pTInfo
);
6335 WARN("Could not search inherited interface!\n");
6337 WARN("no names found\n");
6338 return DISP_E_UNKNOWNNAME
;
6344 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6345 extern double call_double_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6346 __ASM_GLOBAL_FUNC( call_method
,
6348 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6349 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6350 "movl %esp,%ebp\n\t"
6351 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6353 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6355 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6356 "movl 12(%ebp),%edx\n\t"
6357 "movl %esp,%edi\n\t"
6360 "subl %edx,%edi\n\t"
6361 "andl $~15,%edi\n\t"
6362 "movl %edi,%esp\n\t"
6363 "movl 12(%ebp),%ecx\n\t"
6364 "movl 16(%ebp),%esi\n\t"
6367 "1:\tcall *8(%ebp)\n\t"
6368 "subl %esp,%edi\n\t"
6369 "movl 20(%ebp),%ecx\n\t"
6370 "movl %edi,(%ecx)\n\t"
6371 "leal -8(%ebp),%esp\n\t"
6373 __ASM_CFI(".cfi_same_value %edi\n\t")
6375 __ASM_CFI(".cfi_same_value %esi\n\t")
6377 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6378 __ASM_CFI(".cfi_same_value %ebp\n\t")
6380 __ASM_GLOBAL_FUNC( call_double_method
,
6381 "jmp " __ASM_NAME("call_method") )
6383 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6384 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6386 int argspos
= 0, stack_offset
;
6391 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6392 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6393 pvargResult
, V_VT(pvargResult
));
6395 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6397 FIXME("unsupported calling convention %d\n",cc
);
6398 return E_INVALIDARG
;
6401 /* maximum size for an argument is sizeof(VARIANT) */
6402 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6406 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6407 func
= vtable
[oVft
/sizeof(void *)];
6408 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6410 else func
= (void *)oVft
;
6416 args
[argspos
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6419 WARN("invalid return type %u\n", vtReturn
);
6421 return E_INVALIDARG
;
6426 for (i
= 0; i
< cActuals
; i
++)
6428 VARIANT
*arg
= prgpvarg
[i
];
6439 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6440 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6444 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6445 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6447 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6448 args
[argspos
++] = V_BOOL(arg
);
6451 args
[argspos
++] = V_UI4(arg
);
6454 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6462 call_method( func
, argspos
, args
, &stack_offset
);
6465 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6469 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6474 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6477 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6481 if (stack_offset
&& cc
== CC_STDCALL
)
6483 WARN( "stack pointer off by %d\n", stack_offset
);
6484 return DISP_E_BADCALLEE
;
6486 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6487 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6491 #elif defined(__x86_64__)
6493 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6494 extern double CDECL
call_double_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6495 __ASM_GLOBAL_FUNC( call_method
,
6497 __ASM_SEH(".seh_pushreg %rbp\n\t")
6498 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6499 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6500 "movq %rsp,%rbp\n\t"
6501 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6502 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6504 __ASM_SEH(".seh_pushreg %rsi\n\t")
6505 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6507 __ASM_SEH(".seh_pushreg %rdi\n\t")
6508 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6509 __ASM_SEH(".seh_endprologue\n\t")
6510 "movq %rcx,%rax\n\t"
6513 "cmovgq %rdx,%rcx\n\t"
6514 "leaq 0(,%rcx,8),%rdx\n\t"
6515 "subq %rdx,%rsp\n\t"
6516 "andq $~15,%rsp\n\t"
6517 "movq %rsp,%rdi\n\t"
6520 "movq 0(%rsp),%rcx\n\t"
6521 "movq 8(%rsp),%rdx\n\t"
6522 "movq 16(%rsp),%r8\n\t"
6523 "movq 24(%rsp),%r9\n\t"
6524 "movq 0(%rsp),%xmm0\n\t"
6525 "movq 8(%rsp),%xmm1\n\t"
6526 "movq 16(%rsp),%xmm2\n\t"
6527 "movq 24(%rsp),%xmm3\n\t"
6529 "leaq -16(%rbp),%rsp\n\t"
6531 __ASM_CFI(".cfi_same_value %rdi\n\t")
6533 __ASM_CFI(".cfi_same_value %rsi\n\t")
6534 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6536 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6537 __ASM_CFI(".cfi_same_value %rbp\n\t")
6539 __ASM_GLOBAL_FUNC( call_double_method
,
6540 "jmp " __ASM_NAME("call_method") )
6542 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6543 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6550 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6551 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6552 pvargResult
, V_VT(pvargResult
));
6554 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6556 FIXME("unsupported calling convention %d\n",cc
);
6557 return E_INVALIDARG
;
6560 /* maximum size for an argument is sizeof(DWORD_PTR) */
6561 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6565 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6566 func
= vtable
[oVft
/sizeof(void *)];
6567 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6569 else func
= (void *)oVft
;
6575 args
[argspos
++] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6578 WARN("invalid return type %u\n", vtReturn
);
6580 return E_INVALIDARG
;
6585 for (i
= 0; i
< cActuals
; i
++)
6587 VARIANT
*arg
= prgpvarg
[i
];
6593 args
[argspos
++] = (ULONG_PTR
)arg
;
6595 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6596 args
[argspos
++] = V_BOOL(arg
);
6599 args
[argspos
++] = V_UI8(arg
);
6602 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6608 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
);
6612 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
);
6616 call_method( func
, argspos
, args
);
6619 V_UI8(pvargResult
) = call_method( func
, argspos
, args
);
6623 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6624 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6628 #elif defined(__arm__)
6630 extern LONGLONG CDECL
call_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6631 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6632 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6633 __ASM_GLOBAL_FUNC( call_method
,
6636 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6637 * 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)
6640 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6641 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6643 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6644 "beq 1f\n\t" /* Skip allocation if no stack args */
6645 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6646 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6647 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6648 "subs r1, r1, #4\n\t" /* Decrement count */
6649 "bgt 2b\n\t" /* Loop till done */
6653 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6655 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6656 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6658 "blx ip\n\t" /* Call the target function */
6660 "mov sp, fp\n\t" /* Clean the stack using fp */
6661 "pop {fp, pc}\n\t" /* Restore fp and return */
6663 __ASM_GLOBAL_FUNC( call_float_method
,
6664 "b " __ASM_NAME("call_method") )
6665 __ASM_GLOBAL_FUNC( call_double_method
,
6666 "b " __ASM_NAME("call_method") )
6668 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6669 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6684 int rcount
; /* 32-bit register index count */
6686 int scount
= 0; /* single-precision float register index count */
6687 int dcount
= 0; /* double-precision float register index count */
6690 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6691 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6693 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6695 FIXME("unsupported calling convention %d\n",cc
);
6696 return E_INVALIDARG
;
6704 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6705 func
= vtable
[oVft
/sizeof(void *)];
6706 regs
.r
[rcount
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6708 else func
= (void *)oVft
;
6710 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6711 /* first as it will need to be in the 'r' registers: */
6716 regs
.r
[rcount
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6719 WARN("invalid return type %u\n", vtReturn
);
6720 return E_INVALIDARG
;
6721 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6725 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6726 args
= heap_alloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 4 );
6728 for (i
= 0; i
< cActuals
; i
++)
6730 VARIANT
*arg
= prgpvarg
[i
];
6731 DWORD
*pdwarg
= (DWORD
*)(arg
); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6732 int ntemp
; /* Used for counting words split between registers and stack */
6738 case VT_R8
: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6741 dcount
= max( (scount
+ 1) / 2, dcount
);
6744 regs
.sd
.d
[dcount
++] = V_R8(arg
);
6748 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6749 memcpy( &args
[argspos
], &V_R8(arg
), sizeof(V_R8(arg
)) );
6750 argspos
+= sizeof(V_R8(arg
)) / sizeof(DWORD
);
6754 case VT_I8
: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6759 rcount
+= (rcount
% 2); /* align rcount to 8-byte register pair */
6760 memcpy( ®s
.r
[rcount
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6761 rcount
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6765 rcount
= 4; /* Make sure we flag that all 'r' regs are full */
6766 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6767 memcpy( &args
[argspos
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6768 argspos
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6771 case VT_DECIMAL
: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6773 /* 8-byte align 'r' and/or stack: */
6775 rcount
+= (rcount
% 2);
6779 argspos
+= (argspos
% 2);
6781 ntemp
= sizeof(*arg
) / sizeof(DWORD
);
6785 regs
.r
[rcount
++] = *pdwarg
++;
6787 args
[argspos
++] = *pdwarg
++;
6791 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6793 regs
.r
[rcount
++] = V_BOOL(arg
);
6795 args
[argspos
++] = V_BOOL(arg
);
6797 case VT_R4
: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6799 if (!(scount
% 2)) scount
= max( scount
, dcount
* 2 );
6801 regs
.sd
.s
[scount
++] = V_R4(arg
);
6803 args
[argspos
++] = V_UI4(arg
);
6808 regs
.r
[rcount
++] = V_UI4(arg
);
6810 args
[argspos
++] = V_UI4(arg
);
6813 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6816 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 8-byte */
6820 case VT_EMPTY
: /* EMPTY = no return value */
6821 case VT_DECIMAL
: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6823 call_method( func
, argspos
, args
, (DWORD
*)®s
);
6826 V_R4(pvargResult
) = call_float_method( func
, argspos
, args
, (DWORD
*)®s
);
6830 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, (DWORD
*)®s
);
6835 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6838 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6842 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6843 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6847 #elif defined(__aarch64__)
6849 extern DWORD_PTR CDECL
call_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6850 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6851 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6852 __ASM_GLOBAL_FUNC( call_method
,
6853 "stp x29, x30, [sp, #-16]!\n\t"
6855 "sub sp, sp, x1, lsl #3\n\t"
6857 "1:\tsub x1, x1, #1\n\t"
6858 "ldr x4, [x2, x1, lsl #3]\n\t"
6859 "str x4, [sp, x1, lsl #3]\n\t"
6861 "2:\tmov x16, x0\n\t"
6863 "ldp d0, d1, [x9]\n\t"
6864 "ldp d2, d3, [x9, #0x10]\n\t"
6865 "ldp d4, d5, [x9, #0x20]\n\t"
6866 "ldp d6, d7, [x9, #0x30]\n\t"
6867 "ldp x0, x1, [x9, #0x40]\n\t"
6868 "ldp x2, x3, [x9, #0x50]\n\t"
6869 "ldp x4, x5, [x9, #0x60]\n\t"
6870 "ldp x6, x7, [x9, #0x70]\n\t"
6871 "ldr x8, [x9, #0x80]\n\t"
6874 "ldp x29, x30, [sp], #16\n\t"
6876 __ASM_GLOBAL_FUNC( call_float_method
,
6877 "b " __ASM_NAME("call_method") )
6878 __ASM_GLOBAL_FUNC( call_double_method
,
6879 "b " __ASM_NAME("call_method") )
6881 HRESULT WINAPI
DispCallFunc( void *instance
, ULONG_PTR offset
, CALLCONV cc
, VARTYPE ret_type
, UINT count
,
6882 VARTYPE
*types
, VARIANTARG
**vargs
, VARIANT
*result
)
6897 int rcount
; /* 64-bit register index count */
6898 int fpcount
= 0; /* float register index count */
6900 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6901 instance
, offset
, cc
, ret_type
, count
, types
, vargs
, result
, V_VT(result
));
6903 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6905 FIXME("unsupported calling convention %d\n",cc
);
6906 return E_INVALIDARG
;
6914 const FARPROC
*vtable
= *(FARPROC
**)instance
;
6915 func
= vtable
[offset
/sizeof(void *)];
6916 regs
.x
[rcount
++] = (DWORD_PTR
)instance
; /* the This pointer is always the first parameter */
6918 else func
= (void *)offset
;
6920 /* maximum size for an argument is 16 */
6921 args
= heap_alloc( 16 * count
);
6923 for (i
= 0; i
< count
; i
++)
6925 VARIANT
*arg
= vargs
[i
];
6930 if (fpcount
< 8) regs
.fp
[fpcount
++].f
= V_R4(arg
);
6931 else *(float *)&args
[argspos
++] = V_R4(arg
);
6935 if (fpcount
< 8) regs
.fp
[fpcount
++].d
= V_R8(arg
);
6936 else *(double *)&args
[argspos
++] = V_R8(arg
);
6941 memcpy( ®s
.x
[rcount
], arg
, sizeof(*arg
) );
6946 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6951 if (rcount
< 8) regs
.x
[rcount
++] = (DWORD_PTR
)arg
;
6952 else args
[argspos
++] = (DWORD_PTR
)arg
;
6954 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6955 if (rcount
< 8) regs
.x
[rcount
++] = V_BOOL(arg
);
6956 else args
[argspos
++] = V_BOOL(arg
);
6959 if (rcount
< 8) regs
.x
[rcount
++] = V_UI8(arg
);
6960 else args
[argspos
++] = V_UI8(arg
);
6963 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(types
[i
]), debugstr_variant(arg
));
6966 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 16-byte */
6972 return E_INVALIDARG
;
6975 regs
.x
[8] = (DWORD_PTR
)result
; /* x8 is a pointer to the result */
6976 call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6979 V_R4(result
) = call_float_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6983 V_R8(result
) = call_double_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6986 V_UI8(result
) = call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6990 if (ret_type
!= VT_VARIANT
) V_VT(result
) = ret_type
;
6991 TRACE("retval: %s\n", debugstr_variant(result
));
6995 #else /* __aarch64__ */
6997 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6998 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
7000 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7001 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
7007 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
7010 ITypeInfo
*tinfo2
= NULL
;
7011 TYPEATTR
*tattr
= NULL
;
7013 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
7016 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
7018 tdesc
->u
.hreftype
, hr
);
7021 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
7024 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
7025 ITypeInfo_Release(tinfo2
);
7029 switch (tattr
->typekind
)
7036 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
7039 case TKIND_INTERFACE
:
7040 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
7046 case TKIND_DISPATCH
:
7055 FIXME("TKIND_RECORD unhandled.\n");
7060 FIXME("TKIND_UNION unhandled.\n");
7065 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
7069 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7070 ITypeInfo_Release(tinfo2
);
7074 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
7078 /* enforce only one level of pointer indirection */
7079 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
7081 tdesc
= tdesc
->u
.lptdesc
;
7083 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7084 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7085 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7086 if ((tdesc
->vt
== VT_USERDEFINED
) ||
7087 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
7089 VARTYPE vt_userdefined
= 0;
7090 const TYPEDESC
*tdesc_userdefined
= tdesc
;
7091 if (tdesc
->vt
== VT_PTR
)
7093 vt_userdefined
= VT_BYREF
;
7094 tdesc_userdefined
= tdesc
->u
.lptdesc
;
7096 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
7098 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
7099 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
7101 *vt
|= vt_userdefined
;
7113 case VT_USERDEFINED
:
7114 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
7121 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
7122 hr
= DISP_E_BADVARTYPE
;
7126 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
7141 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, HREFTYPE href
, GUID
*guid
)
7148 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
7152 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
7154 ITypeInfo_Release(tinfo2
);
7158 switch(tattr
->typekind
) {
7160 hres
= get_iface_guid(tinfo2
, tattr
->tdescAlias
.u
.hreftype
, guid
);
7163 case TKIND_INTERFACE
:
7164 case TKIND_DISPATCH
:
7165 *guid
= tattr
->guid
;
7169 for (i
= 0; i
< tattr
->cImplTypes
; i
++)
7171 ITypeInfo_GetImplTypeFlags(tinfo2
, i
, &flags
);
7172 if (flags
& IMPLTYPEFLAG_FDEFAULT
)
7176 if (i
== tattr
->cImplTypes
)
7179 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo2
, i
, &href
);
7180 if (SUCCEEDED(hres
))
7181 hres
= get_iface_guid(tinfo2
, href
, guid
);
7185 ERR("Unexpected typekind %d\n", tattr
->typekind
);
7186 hres
= E_UNEXPECTED
;
7189 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7190 ITypeInfo_Release(tinfo2
);
7194 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
7196 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
7199 #define INVBUF_ELEMENT_SIZE \
7200 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7201 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7202 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7203 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7204 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7205 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7206 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7207 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7209 static HRESULT WINAPI
ITypeInfo_fnInvoke(
7214 DISPPARAMS
*pDispParams
,
7215 VARIANT
*pVarResult
,
7216 EXCEPINFO
*pExcepInfo
,
7219 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7221 unsigned int var_index
;
7224 const TLBFuncDesc
*pFuncInfo
;
7227 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7228 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
7231 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7232 return DISP_E_MEMBERNOTFOUND
;
7236 ERR("NULL pDispParams not allowed\n");
7237 return E_INVALIDARG
;
7240 dump_DispParms(pDispParams
);
7242 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7244 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7245 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7246 return E_INVALIDARG
;
7249 /* we do this instead of using GetFuncDesc since it will return a fake
7250 * FUNCDESC for dispinterfaces and we want the real function description */
7251 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7252 pFuncInfo
= &This
->funcdescs
[fdc
];
7253 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7254 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7255 !func_restricted( &pFuncInfo
->funcdesc
))
7259 if (fdc
< This
->typeattr
.cFuncs
) {
7260 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7264 TRACE("invoking:\n");
7265 dump_TLBFuncDescOne(pFuncInfo
);
7268 switch (func_desc
->funckind
) {
7269 case FUNC_PUREVIRTUAL
:
7270 case FUNC_VIRTUAL
: {
7271 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7273 VARIANT retval
= {{{0}}}; /* pointer for storing byref retvals in */
7274 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7275 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7276 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7277 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7278 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7279 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7280 UINT vargs_converted
=0;
7285 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7287 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7289 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7290 hres
= DISP_E_PARAMNOTFOUND
;
7295 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7297 ERR("functions with the vararg attribute do not support named arguments\n");
7298 hres
= DISP_E_NONAMEDARGS
;
7302 for (i
= 0; i
< func_desc
->cParams
; i
++)
7304 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7305 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7310 TRACE("changing args\n");
7311 for (i
= 0; i
< func_desc
->cParams
; i
++)
7313 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7314 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7315 VARIANTARG
*src_arg
;
7317 if (wParamFlags
& PARAMFLAG_FLCID
)
7319 prgpvarg
[i
] = &rgvarg
[i
];
7320 V_VT(prgpvarg
[i
]) = VT_I4
;
7321 V_I4(prgpvarg
[i
]) = 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)
7362 prgpvarg
[i
] = &rgvarg
[i
];
7363 V_BYREF(prgpvarg
[i
]) = &retval
;
7364 V_VT(prgpvarg
[i
]) = rgvt
[i
];
7368 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7369 hres
= E_UNEXPECTED
;
7373 else if (src_arg
&& !((wParamFlags
& PARAMFLAG_FOPT
) &&
7374 V_VT(src_arg
) == VT_ERROR
&& V_ERROR(src_arg
) == DISP_E_PARAMNOTFOUND
))
7376 TRACE("%s\n", debugstr_variant(src_arg
));
7378 if(rgvt
[i
]!=V_VT(src_arg
))
7380 if (rgvt
[i
] == VT_VARIANT
)
7381 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7382 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7384 if (rgvt
[i
] == V_VT(src_arg
))
7385 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7388 if (wParamFlags
& PARAMFLAG_FIN
)
7389 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7390 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7392 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7394 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7396 SAFEARRAYBOUND bound
;
7400 bound
.cElements
= pDispParams
->cArgs
-i
;
7401 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7403 ERR("SafeArrayCreate failed\n");
7406 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7409 ERR("SafeArrayAccessData failed with %x\n", hres
);
7410 SafeArrayDestroy(a
);
7413 for (j
= 0; j
< bound
.cElements
; j
++)
7414 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7415 hres
= SafeArrayUnaccessData(a
);
7418 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7419 SafeArrayDestroy(a
);
7422 if (rgvt
[i
] & VT_BYREF
)
7423 V_BYREF(&rgvarg
[i
]) = &a
;
7425 V_ARRAY(&rgvarg
[i
]) = a
;
7426 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7428 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7430 if (wParamFlags
& PARAMFLAG_FIN
)
7431 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7433 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7434 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7435 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7437 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7439 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7440 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7444 /* FIXME: this doesn't work for VT_BYREF arguments if
7445 * they are not the same type as in the paramdesc */
7446 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7447 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7448 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7453 ERR("failed to convert param %d to %s from %s\n", i
,
7454 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7457 prgpvarg
[i
] = &rgvarg
[i
];
7461 prgpvarg
[i
] = src_arg
;
7464 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7465 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7466 && V_UNKNOWN(prgpvarg
[i
])) {
7467 IUnknown
*userdefined_iface
;
7470 if (tdesc
->vt
== VT_PTR
)
7471 tdesc
= tdesc
->u
.lptdesc
;
7473 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->u
.hreftype
, &guid
);
7477 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7479 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7483 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7484 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7487 else if (wParamFlags
& PARAMFLAG_FOPT
)
7490 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7491 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7493 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7499 /* if the function wants a pointer to a variant then
7500 * set that up, otherwise just pass the VT_ERROR in
7501 * the argument by value */
7502 if (rgvt
[i
] & VT_BYREF
)
7504 V_VT(&missing_arg
[i
]) = VT_ERROR
;
7505 V_ERROR(&missing_arg
[i
]) = DISP_E_PARAMNOTFOUND
;
7507 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7508 V_VARIANTREF(arg
) = &missing_arg
[i
];
7512 V_VT(arg
) = VT_ERROR
;
7513 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
7519 hres
= DISP_E_BADPARAMCOUNT
;
7523 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7525 /* VT_VOID is a special case for return types, so it is not
7526 * handled in the general function */
7527 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7528 V_VT(&varresult
) = VT_EMPTY
;
7531 V_VT(&varresult
) = 0;
7532 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7533 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7536 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7537 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7538 prgpvarg
, &varresult
);
7540 vargs_converted
= 0;
7542 for (i
= 0; i
< func_desc
->cParams
; i
++)
7544 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7546 if (wParamFlags
& PARAMFLAG_FLCID
)
7548 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7550 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7554 VariantInit(pVarResult
);
7555 /* deref return value */
7556 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7559 VARIANT_ClearInd(prgpvarg
[i
]);
7561 else if (vargs_converted
< pDispParams
->cArgs
)
7563 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7564 if (wParamFlags
& PARAMFLAG_FOUT
)
7566 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7568 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7572 ERR("failed to convert param %d to vt %d\n", i
,
7573 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7578 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7579 func_desc
->cParamsOpt
< 0 &&
7580 i
== func_desc
->cParams
-1)
7582 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7585 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7588 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7591 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7594 ERR("SafeArrayAccessData failed with %x\n", hres
);
7597 for (j
= 0; j
<= ubound
; j
++)
7598 VariantClear(&v
[j
]);
7599 hres
= SafeArrayUnaccessData(a
);
7602 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7606 VariantClear(&rgvarg
[i
]);
7609 else if (wParamFlags
& PARAMFLAG_FOPT
)
7611 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7612 VariantClear(&rgvarg
[i
]);
7615 VariantClear(&missing_arg
[i
]);
7618 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7620 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7621 hres
= DISP_E_EXCEPTION
;
7624 IErrorInfo
*pErrorInfo
;
7625 pExcepInfo
->scode
= V_ERROR(&varresult
);
7626 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7628 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7629 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7630 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7631 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7633 IErrorInfo_Release(pErrorInfo
);
7637 if (V_VT(&varresult
) != VT_ERROR
)
7639 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7643 VariantClear(pVarResult
);
7644 *pVarResult
= varresult
;
7647 VariantClear(&varresult
);
7650 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7651 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7652 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7653 (pDispParams
->cArgs
!= 0))
7655 if (V_VT(pVarResult
) == VT_DISPATCH
)
7657 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7658 /* Note: not VariantClear; we still need the dispatch
7659 * pointer to be valid */
7660 VariantInit(pVarResult
);
7661 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7662 GetSystemDefaultLCID(), wFlags
,
7663 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7664 IDispatch_Release(pDispatch
);
7668 VariantClear(pVarResult
);
7669 hres
= DISP_E_NOTACOLLECTION
;
7677 case FUNC_DISPATCH
: {
7680 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7681 if (SUCCEEDED(hres
)) {
7682 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7683 hres
= IDispatch_Invoke(
7684 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7685 pVarResult
,pExcepInfo
,pArgErr
7688 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7689 IDispatch_Release(disp
);
7691 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7695 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7700 TRACE("-- 0x%08x\n", hres
);
7703 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7706 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7707 if(FAILED(hres
)) return hres
;
7709 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7710 dump_VARDESC(var_desc
);
7711 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7715 /* not found, look for it in inherited interfaces */
7716 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7717 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7718 if(This
->impltypes
) {
7719 /* recursive search */
7721 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7722 if(SUCCEEDED(hres
)){
7723 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7724 ITypeInfo_Release(pTInfo
);
7727 WARN("Could not search inherited interface!\n");
7730 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7731 return DISP_E_MEMBERNOTFOUND
;
7734 /* ITypeInfo::GetDocumentation
7736 * Retrieves the documentation string, the complete Help file name and path,
7737 * and the context ID for the Help topic for a specified type description.
7739 * (Can be tested by the Visual Basic Editor in Word for instance.)
7741 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7742 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7743 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7745 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7746 const TLBFuncDesc
*pFDesc
;
7747 const TLBVarDesc
*pVDesc
;
7748 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7749 " HelpContext(%p) HelpFile(%p)\n",
7750 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7751 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7753 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7755 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7757 *pdwHelpContext
=This
->dwHelpContext
;
7759 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7761 }else {/* for a member */
7762 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
7765 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7767 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7769 *pdwHelpContext
=pFDesc
->helpcontext
;
7771 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7774 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
7777 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7779 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7781 *pdwHelpContext
=pVDesc
->HelpContext
;
7783 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7788 if(This
->impltypes
&&
7789 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7790 /* recursive search */
7793 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7794 if(SUCCEEDED(result
)) {
7795 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7796 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7797 ITypeInfo_Release(pTInfo
);
7800 WARN("Could not search inherited interface!\n");
7803 WARN("member %d not found\n", memid
);
7804 return TYPE_E_ELEMENTNOTFOUND
;
7807 /* ITypeInfo::GetDllEntry
7809 * Retrieves a description or specification of an entry point for a function
7812 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7813 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7816 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7817 const TLBFuncDesc
*pFDesc
;
7819 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7821 if (pBstrDllName
) *pBstrDllName
= NULL
;
7822 if (pBstrName
) *pBstrName
= NULL
;
7823 if (pwOrdinal
) *pwOrdinal
= 0;
7825 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7826 return TYPE_E_BADMODULEKIND
;
7828 pFDesc
= TLB_get_funcdesc_by_memberid_invkind(This
, memid
, invKind
);
7829 if (!pFDesc
) return TYPE_E_ELEMENTNOTFOUND
;
7831 dump_TypeInfo(This
);
7832 if (TRACE_ON(ole
)) dump_TLBFuncDescOne(pFDesc
);
7834 if (pBstrDllName
) *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7836 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1))
7838 if (pBstrName
) *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7839 if (pwOrdinal
) *pwOrdinal
= -1;
7843 if (pBstrName
) *pBstrName
= NULL
;
7844 if (pwOrdinal
) *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7849 /* internal function to make the inherited interfaces' methods appear
7850 * part of the interface */
7851 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7852 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7854 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7857 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7859 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7861 ITypeInfo
*pSubTypeInfo
;
7863 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7867 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7869 ITypeInfo_Release(pSubTypeInfo
);
7873 *hRefType
-= DISPATCH_HREF_OFFSET
;
7875 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7876 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7881 /* ITypeInfo::GetRefTypeInfo
7883 * If a type description references other type descriptions, it retrieves
7884 * the referenced type descriptions.
7886 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7889 ITypeInfo
**ppTInfo
)
7891 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7892 ITypeInfo
*type_info
= NULL
;
7893 HRESULT result
= E_FAIL
;
7894 TLBRefType
*ref_type
;
7898 return E_INVALIDARG
;
7900 if ((INT
)hRefType
< 0) {
7901 ITypeInfoImpl
*pTypeInfoImpl
;
7903 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7904 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7905 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7906 return TYPE_E_ELEMENTNOTFOUND
;
7908 /* when we meet a DUAL typeinfo, we must create the alternate
7911 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7913 *pTypeInfoImpl
= *This
;
7914 pTypeInfoImpl
->ref
= 0;
7915 list_init(&pTypeInfoImpl
->custdata_list
);
7917 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7918 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7920 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7922 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7923 /* the AddRef implicitly adds a reference to the parent typelib, which
7924 * stops the copied data from being destroyed until the new typeinfo's
7925 * refcount goes to zero, but we need to signal to the new instance to
7926 * not free its data structures when it is destroyed */
7927 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7928 ITypeInfo_AddRef(*ppTInfo
);
7930 TRACE("got dual interface %p\n", *ppTInfo
);
7934 if ((hRefType
& DISPATCH_HREF_MASK
) && (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7935 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &hRefType
, ppTInfo
);
7937 if(!(hRefType
& 0x1))
7939 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7941 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7944 type_info
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7945 ITypeInfo_AddRef(type_info
);
7953 ITypeLib
*pTLib
= NULL
;
7955 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7957 if(ref_type
->reference
== (hRefType
& (~0x3)))
7960 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7962 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7966 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7968 TRACE("internal reference\n");
7969 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7971 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7972 TRACE("typeinfo in imported typelib that is already loaded\n");
7973 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7974 ITypeLib_AddRef(pTLib
);
7977 /* Search in cached typelibs */
7978 ITypeLibImpl
*entry
;
7980 EnterCriticalSection(&cache_section
);
7981 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
7984 && IsEqualIID(&entry
->guid
->guid
, TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
))
7985 && entry
->ver_major
== ref_type
->pImpTLInfo
->wVersionMajor
7986 && entry
->ver_minor
== ref_type
->pImpTLInfo
->wVersionMinor
7987 && entry
->set_lcid
== ref_type
->pImpTLInfo
->lcid
)
7989 TRACE("got cached %p\n", entry
);
7990 pTLib
= (ITypeLib
*)&entry
->ITypeLib2_iface
;
7991 ITypeLib_AddRef(pTLib
);
7996 LeaveCriticalSection(&cache_section
);
8002 /* Search on disk */
8003 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
8004 ref_type
->pImpTLInfo
->wVersionMajor
,
8005 ref_type
->pImpTLInfo
->wVersionMinor
,
8006 This
->pTypeLib
->syskind
,
8007 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
8009 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
8011 result
= LoadTypeLib(libnam
, &pTLib
);
8012 SysFreeString(libnam
);
8015 if(SUCCEEDED(result
)) {
8016 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
8017 ITypeLib_AddRef(pTLib
);
8021 if(SUCCEEDED(result
)) {
8022 if(ref_type
->index
== TLB_REF_USE_GUID
)
8023 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), &type_info
);
8025 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, &type_info
);
8028 ITypeLib_Release(pTLib
);
8031 WARN("(%p) failed hreftype 0x%04x\n", This
, hRefType
);
8036 if ((hRefType
& 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info
, -2, ppTInfo
)))
8037 ITypeInfo_Release(type_info
);
8038 else *ppTInfo
= type_info
;
8040 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
8041 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
8045 /* ITypeInfo::AddressOfMember
8047 * Retrieves the addresses of static functions or variables, such as those
8050 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
8051 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
8053 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8059 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
8061 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
8065 module
= LoadLibraryW(dll
);
8068 ERR("couldn't load %s\n", debugstr_w(dll
));
8070 SysFreeString(entry
);
8071 return STG_E_FILENOTFOUND
;
8073 /* FIXME: store library somewhere where we can free it */
8078 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
8079 entryA
= heap_alloc(len
);
8080 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
8082 *ppv
= GetProcAddress(module
, entryA
);
8084 ERR("function not found %s\n", debugstr_a(entryA
));
8090 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
8092 ERR("function not found %d\n", ordinal
);
8096 SysFreeString(entry
);
8099 return TYPE_E_DLLFUNCTIONNOTFOUND
;
8104 /* ITypeInfo::CreateInstance
8106 * Creates a new instance of a type that describes a component object class
8109 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
8110 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
8112 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8116 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
8122 WARN("Not able to aggregate\n");
8123 return CLASS_E_NOAGGREGATION
;
8126 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
8127 if(FAILED(hr
)) return hr
;
8129 if(pTA
->typekind
!= TKIND_COCLASS
)
8131 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
8137 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
8140 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
8141 TRACE("GetActiveObject rets %08x\n", hr
);
8144 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
8145 IUnknown_Release(pUnk
);
8150 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
8151 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8155 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8159 /* ITypeInfo::GetMops
8161 * Retrieves marshalling information.
8163 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
8166 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8167 FIXME("(%p %d) stub!\n", This
, memid
);
8172 /* ITypeInfo::GetContainingTypeLib
8174 * Retrieves the containing type library and the index of the type description
8175 * within that type library.
8177 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8178 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8180 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8182 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8184 *pIndex
=This
->index
;
8185 TRACE("returning pIndex=%d\n", *pIndex
);
8189 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8190 ITypeLib_AddRef(*ppTLib
);
8191 TRACE("returning ppTLib=%p\n", *ppTLib
);
8197 /* ITypeInfo::ReleaseTypeAttr
8199 * Releases a TYPEATTR previously returned by Get
8202 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8203 TYPEATTR
* pTypeAttr
)
8205 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8206 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8207 heap_free(pTypeAttr
);
8210 /* ITypeInfo::ReleaseFuncDesc
8212 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8214 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8216 FUNCDESC
*pFuncDesc
)
8218 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8221 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8223 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8224 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8225 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8227 SysFreeString((BSTR
)pFuncDesc
);
8230 /* ITypeInfo::ReleaseVarDesc
8232 * Releases a VARDESC previously returned by GetVarDesc.
8234 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8237 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8238 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8240 TLB_FreeVarDesc(pVarDesc
);
8243 /* ITypeInfo2::GetTypeKind
8245 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8248 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8249 TYPEKIND
*pTypeKind
)
8251 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8252 *pTypeKind
= This
->typeattr
.typekind
;
8253 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8257 /* ITypeInfo2::GetTypeFlags
8259 * Returns the type flags without any allocations. This returns a DWORD type
8260 * flag, which expands the type flags without growing the TYPEATTR (type
8264 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8266 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8267 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8268 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
8272 /* ITypeInfo2::GetFuncIndexOfMemId
8273 * Binds to a specific member based on a known DISPID, where the member name
8274 * is not known (for example, when binding to a default member).
8277 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8278 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8280 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8284 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8285 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8286 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8289 if(fdc
< This
->typeattr
.cFuncs
) {
8293 result
= TYPE_E_ELEMENTNOTFOUND
;
8295 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
8296 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8300 /* TypeInfo2::GetVarIndexOfMemId
8302 * Binds to a specific member based on a known DISPID, where the member name
8303 * is not known (for example, when binding to a default member).
8306 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8307 MEMBERID memid
, UINT
*pVarIndex
)
8309 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8310 TLBVarDesc
*pVarInfo
;
8312 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8314 pVarInfo
= TLB_get_vardesc_by_memberid(This
, memid
);
8316 return TYPE_E_ELEMENTNOTFOUND
;
8318 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8323 /* ITypeInfo2::GetCustData
8325 * Gets the custom data
8327 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8332 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8333 TLBCustData
*pCData
;
8335 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8337 if(!guid
|| !pVarVal
)
8338 return E_INVALIDARG
;
8340 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8342 VariantInit( pVarVal
);
8344 VariantCopy( pVarVal
, &pCData
->data
);
8346 VariantClear( pVarVal
);
8350 /* ITypeInfo2::GetFuncCustData
8352 * Gets the custom data
8354 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8360 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8361 const TLBFuncDesc
*desc
;
8366 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8368 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &desc
, &hrefoffset
);
8371 WARN("description for function %d not found\n", index
);
8375 VariantInit(pVarVal
);
8376 data
= TLB_get_custdata_by_guid(&desc
->custdata_list
, guid
);
8377 return data
? VariantCopy(pVarVal
, &data
->data
) : S_OK
;
8380 /* ITypeInfo2::GetParamCustData
8382 * Gets the custom data
8384 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8391 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8392 const TLBFuncDesc
*pFDesc
;
8393 TLBCustData
*pCData
;
8397 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8398 debugstr_guid(guid
), pVarVal
);
8400 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8404 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8405 return TYPE_E_ELEMENTNOTFOUND
;
8407 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8409 return TYPE_E_ELEMENTNOTFOUND
;
8411 VariantInit(pVarVal
);
8412 VariantCopy(pVarVal
, &pCData
->data
);
8417 /* ITypeInfo2::GetVarCustData
8419 * Gets the custom data
8421 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8427 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8428 TLBCustData
*pCData
;
8429 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8431 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8433 if(index
>= This
->typeattr
.cVars
)
8434 return TYPE_E_ELEMENTNOTFOUND
;
8436 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8438 return TYPE_E_ELEMENTNOTFOUND
;
8440 VariantInit(pVarVal
);
8441 VariantCopy(pVarVal
, &pCData
->data
);
8446 /* ITypeInfo2::GetImplCustData
8448 * Gets the custom data
8450 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8456 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8457 TLBCustData
*pCData
;
8458 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8460 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8462 if(index
>= This
->typeattr
.cImplTypes
)
8463 return TYPE_E_ELEMENTNOTFOUND
;
8465 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8467 return TYPE_E_ELEMENTNOTFOUND
;
8469 VariantInit(pVarVal
);
8470 VariantCopy(pVarVal
, &pCData
->data
);
8475 /* ITypeInfo2::GetDocumentation2
8477 * Retrieves the documentation string, the complete Help file name and path,
8478 * the localization context to use, and the context ID for the library Help
8479 * topic in the Help file.
8482 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8486 BSTR
*pbstrHelpString
,
8487 DWORD
*pdwHelpStringContext
,
8488 BSTR
*pbstrHelpStringDll
)
8490 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8491 const TLBFuncDesc
*pFDesc
;
8492 const TLBVarDesc
*pVDesc
;
8493 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8494 "HelpStringContext(%p) HelpStringDll(%p)\n",
8495 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8496 pbstrHelpStringDll
);
8497 /* the help string should be obtained from the helpstringdll,
8498 * using the _DLLGetDocumentation function, based on the supplied
8499 * lcid. Nice to do sometime...
8501 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8503 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8504 if(pdwHelpStringContext
)
8505 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8506 if(pbstrHelpStringDll
)
8507 *pbstrHelpStringDll
=
8508 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8510 }else {/* for a member */
8511 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
8514 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8515 if(pdwHelpStringContext
)
8516 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8517 if(pbstrHelpStringDll
)
8518 *pbstrHelpStringDll
=
8519 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8522 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
8525 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8526 if(pdwHelpStringContext
)
8527 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8528 if(pbstrHelpStringDll
)
8529 *pbstrHelpStringDll
=
8530 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8534 return TYPE_E_ELEMENTNOTFOUND
;
8537 /* ITypeInfo2::GetAllCustData
8539 * Gets all custom data items for the Type info.
8542 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8544 CUSTDATA
*pCustData
)
8546 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8548 TRACE("%p %p\n", This
, pCustData
);
8550 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8553 /* ITypeInfo2::GetAllFuncCustData
8555 * Gets all custom data items for the specified Function
8558 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8561 CUSTDATA
*pCustData
)
8563 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8564 const TLBFuncDesc
*pFDesc
;
8568 TRACE("%p %u %p\n", This
, index
, pCustData
);
8570 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &pFDesc
, &hrefoffset
);
8574 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8577 /* ITypeInfo2::GetAllParamCustData
8579 * Gets all custom data items for the Functions
8582 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8583 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8585 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8586 const TLBFuncDesc
*pFDesc
;
8590 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8592 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8596 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8597 return TYPE_E_ELEMENTNOTFOUND
;
8599 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8602 /* ITypeInfo2::GetAllVarCustData
8604 * Gets all custom data items for the specified Variable
8607 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8608 UINT index
, CUSTDATA
*pCustData
)
8610 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8611 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8613 TRACE("%p %u %p\n", This
, index
, pCustData
);
8615 if(index
>= This
->typeattr
.cVars
)
8616 return TYPE_E_ELEMENTNOTFOUND
;
8618 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8621 /* ITypeInfo2::GetAllImplCustData
8623 * Gets all custom data items for the specified implementation type
8626 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8629 CUSTDATA
*pCustData
)
8631 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8632 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8634 TRACE("%p %u %p\n", This
, index
, pCustData
);
8636 if(index
>= This
->typeattr
.cImplTypes
)
8637 return TYPE_E_ELEMENTNOTFOUND
;
8639 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8642 static const ITypeInfo2Vtbl tinfvt
=
8645 ITypeInfo_fnQueryInterface
,
8647 ITypeInfo_fnRelease
,
8649 ITypeInfo_fnGetTypeAttr
,
8650 ITypeInfo_fnGetTypeComp
,
8651 ITypeInfo_fnGetFuncDesc
,
8652 ITypeInfo_fnGetVarDesc
,
8653 ITypeInfo_fnGetNames
,
8654 ITypeInfo_fnGetRefTypeOfImplType
,
8655 ITypeInfo_fnGetImplTypeFlags
,
8656 ITypeInfo_fnGetIDsOfNames
,
8658 ITypeInfo_fnGetDocumentation
,
8659 ITypeInfo_fnGetDllEntry
,
8660 ITypeInfo_fnGetRefTypeInfo
,
8661 ITypeInfo_fnAddressOfMember
,
8662 ITypeInfo_fnCreateInstance
,
8663 ITypeInfo_fnGetMops
,
8664 ITypeInfo_fnGetContainingTypeLib
,
8665 ITypeInfo_fnReleaseTypeAttr
,
8666 ITypeInfo_fnReleaseFuncDesc
,
8667 ITypeInfo_fnReleaseVarDesc
,
8669 ITypeInfo2_fnGetTypeKind
,
8670 ITypeInfo2_fnGetTypeFlags
,
8671 ITypeInfo2_fnGetFuncIndexOfMemId
,
8672 ITypeInfo2_fnGetVarIndexOfMemId
,
8673 ITypeInfo2_fnGetCustData
,
8674 ITypeInfo2_fnGetFuncCustData
,
8675 ITypeInfo2_fnGetParamCustData
,
8676 ITypeInfo2_fnGetVarCustData
,
8677 ITypeInfo2_fnGetImplTypeCustData
,
8678 ITypeInfo2_fnGetDocumentation2
,
8679 ITypeInfo2_fnGetAllCustData
,
8680 ITypeInfo2_fnGetAllFuncCustData
,
8681 ITypeInfo2_fnGetAllParamCustData
,
8682 ITypeInfo2_fnGetAllVarCustData
,
8683 ITypeInfo2_fnGetAllImplTypeCustData
,
8686 /******************************************************************************
8687 * CreateDispTypeInfo [OLEAUT32.31]
8689 * Build type information for an object so it can be called through an
8690 * IDispatch interface.
8693 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8694 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8697 * This call allows an objects methods to be accessed through IDispatch, by
8698 * building an ITypeInfo object that IDispatch can use to call through.
8700 HRESULT WINAPI
CreateDispTypeInfo(
8701 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8702 LCID lcid
, /* [I] Locale Id */
8703 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8705 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8706 ITypeLibImpl
*pTypeLibImpl
;
8707 unsigned int param
, func
;
8708 TLBFuncDesc
*pFuncDesc
;
8712 pTypeLibImpl
= TypeLibImpl_Constructor();
8713 if (!pTypeLibImpl
) return E_FAIL
;
8715 pTypeLibImpl
->TypeInfoCount
= 2;
8716 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8718 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8719 pTIIface
->pTypeLib
= pTypeLibImpl
;
8720 pTIIface
->index
= 0;
8721 pTIIface
->Name
= NULL
;
8722 pTIIface
->dwHelpContext
= -1;
8723 pTIIface
->guid
= NULL
;
8724 pTIIface
->typeattr
.lcid
= lcid
;
8725 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8726 pTIIface
->typeattr
.wMajorVerNum
= 0;
8727 pTIIface
->typeattr
.wMinorVerNum
= 0;
8728 pTIIface
->typeattr
.cbAlignment
= 2;
8729 pTIIface
->typeattr
.cbSizeInstance
= -1;
8730 pTIIface
->typeattr
.cbSizeVft
= -1;
8731 pTIIface
->typeattr
.cFuncs
= 0;
8732 pTIIface
->typeattr
.cImplTypes
= 0;
8733 pTIIface
->typeattr
.cVars
= 0;
8734 pTIIface
->typeattr
.wTypeFlags
= 0;
8735 pTIIface
->hreftype
= 0;
8737 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8738 pFuncDesc
= pTIIface
->funcdescs
;
8739 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8740 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8741 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8742 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8743 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8744 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8745 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8746 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8747 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8748 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8749 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8750 pFuncDesc
->funcdesc
.cScodes
= 0;
8751 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8752 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8753 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8754 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8755 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8756 md
->cArgs
* sizeof(ELEMDESC
));
8757 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8758 for(param
= 0; param
< md
->cArgs
; param
++) {
8759 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8760 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8762 pFuncDesc
->helpcontext
= 0;
8763 pFuncDesc
->HelpStringContext
= 0;
8764 pFuncDesc
->HelpString
= NULL
;
8765 pFuncDesc
->Entry
= NULL
;
8766 list_init(&pFuncDesc
->custdata_list
);
8767 pTIIface
->typeattr
.cFuncs
++;
8771 dump_TypeInfo(pTIIface
);
8773 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8774 pTIClass
->pTypeLib
= pTypeLibImpl
;
8775 pTIClass
->index
= 1;
8776 pTIClass
->Name
= NULL
;
8777 pTIClass
->dwHelpContext
= -1;
8778 pTIClass
->guid
= NULL
;
8779 pTIClass
->typeattr
.lcid
= lcid
;
8780 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8781 pTIClass
->typeattr
.wMajorVerNum
= 0;
8782 pTIClass
->typeattr
.wMinorVerNum
= 0;
8783 pTIClass
->typeattr
.cbAlignment
= 2;
8784 pTIClass
->typeattr
.cbSizeInstance
= -1;
8785 pTIClass
->typeattr
.cbSizeVft
= -1;
8786 pTIClass
->typeattr
.cFuncs
= 0;
8787 pTIClass
->typeattr
.cImplTypes
= 1;
8788 pTIClass
->typeattr
.cVars
= 0;
8789 pTIClass
->typeattr
.wTypeFlags
= 0;
8790 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8792 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8794 ref
= heap_alloc_zero(sizeof(*ref
));
8795 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8796 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8798 dump_TypeInfo(pTIClass
);
8800 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8802 ITypeInfo_AddRef(*pptinfo
);
8803 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8809 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8811 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8813 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8816 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8818 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8820 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8823 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8825 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8827 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8830 static HRESULT WINAPI
ITypeComp_fnBind(
8835 ITypeInfo
** ppTInfo
,
8836 DESCKIND
* pDescKind
,
8839 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8840 const TLBFuncDesc
*pFDesc
;
8841 const TLBVarDesc
*pVDesc
;
8842 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8845 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8847 *pDescKind
= DESCKIND_NONE
;
8848 pBindPtr
->lpfuncdesc
= NULL
;
8851 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8852 pFDesc
= &This
->funcdescs
[fdc
];
8853 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8854 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8857 /* name found, but wrong flags */
8858 hr
= TYPE_E_TYPEMISMATCH
;
8862 if (fdc
< This
->typeattr
.cFuncs
)
8864 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8866 &pBindPtr
->lpfuncdesc
,
8867 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8870 *pDescKind
= DESCKIND_FUNCDESC
;
8871 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8872 ITypeInfo_AddRef(*ppTInfo
);
8875 pVDesc
= TLB_get_vardesc_by_name(This
, szName
);
8877 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8880 *pDescKind
= DESCKIND_VARDESC
;
8881 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8882 ITypeInfo_AddRef(*ppTInfo
);
8887 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8888 /* recursive search */
8892 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8895 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8896 ITypeInfo_Release(pTInfo
);
8900 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8901 ITypeComp_Release(pTComp
);
8902 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8903 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8905 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8906 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8907 SysFreeString((BSTR
)tmp
);
8911 WARN("Could not search inherited interface!\n");
8913 if (hr
== DISP_E_MEMBERNOTFOUND
)
8915 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8919 static HRESULT WINAPI
ITypeComp_fnBindType(
8923 ITypeInfo
** ppTInfo
,
8924 ITypeComp
** ppTComp
)
8926 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8928 /* strange behaviour (does nothing) but like the
8931 if (!ppTInfo
|| !ppTComp
)
8940 static const ITypeCompVtbl tcompvt
=
8943 ITypeComp_fnQueryInterface
,
8945 ITypeComp_fnRelease
,
8948 ITypeComp_fnBindType
8951 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8952 ICreateTypeLib2
** ppctlib
)
8957 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8959 if (!szFile
) return E_INVALIDARG
;
8961 This
= TypeLibImpl_Constructor();
8963 return E_OUTOFMEMORY
;
8965 This
->lcid
= GetSystemDefaultLCID();
8966 This
->syskind
= syskind
;
8967 This
->ptr_size
= get_ptr_size(syskind
);
8969 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8971 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8972 return E_OUTOFMEMORY
;
8974 lstrcpyW(This
->path
, szFile
);
8976 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8977 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8981 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8982 REFIID riid
, void **object
)
8984 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8986 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8989 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8991 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8993 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8996 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8998 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9000 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
9003 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
9004 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
9006 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9007 ITypeInfoImpl
*info
;
9010 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
9012 if (!ctinfo
|| !name
)
9013 return E_INVALIDARG
;
9015 info
= TLB_get_typeinfo_by_name(This
, name
);
9017 return TYPE_E_NAMECONFLICT
;
9019 if (This
->typeinfos
)
9020 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
9021 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
9023 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
9025 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
9027 info
->pTypeLib
= This
;
9028 info
->Name
= TLB_append_str(&This
->name_list
, name
);
9029 info
->index
= This
->TypeInfoCount
;
9030 info
->typeattr
.typekind
= kind
;
9031 info
->typeattr
.cbAlignment
= 4;
9033 switch (info
->typeattr
.typekind
) {
9035 case TKIND_INTERFACE
:
9036 case TKIND_DISPATCH
:
9038 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
9042 info
->typeattr
.cbSizeInstance
= 0;
9045 info
->typeattr
.cbSizeInstance
= 2;
9048 info
->typeattr
.cbSizeInstance
= -0x75;
9051 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
9052 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
9056 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
9057 &IID_ICreateTypeInfo
, (void **)ctinfo
);
9059 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
9063 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
9065 ++This
->TypeInfoCount
;
9070 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
9073 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9075 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
9078 return E_INVALIDARG
;
9080 This
->Name
= TLB_append_str(&This
->name_list
, name
);
9085 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
9086 WORD majorVerNum
, WORD minorVerNum
)
9088 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9090 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
9092 This
->ver_major
= majorVerNum
;
9093 This
->ver_minor
= minorVerNum
;
9098 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
9101 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9103 TRACE("%p %s\n", This
, debugstr_guid(guid
));
9105 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
9110 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
9113 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9115 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
9118 return E_INVALIDARG
;
9120 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
9125 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
9126 LPOLESTR helpFileName
)
9128 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9130 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
9133 return E_INVALIDARG
;
9135 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
9140 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
9143 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9145 TRACE("%p %d\n", This
, helpContext
);
9147 This
->dwHelpContext
= helpContext
;
9152 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
9155 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9157 TRACE("%p %x\n", This
, lcid
);
9159 This
->set_lcid
= lcid
;
9164 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9167 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9169 TRACE("%p %x\n", This
, libFlags
);
9171 This
->libflags
= libFlags
;
9176 typedef struct tagWMSFT_SegContents
{
9179 } WMSFT_SegContents
;
9181 typedef struct tagWMSFT_TLBFile
{
9183 WMSFT_SegContents typeinfo_seg
;
9184 WMSFT_SegContents impfile_seg
;
9185 WMSFT_SegContents impinfo_seg
;
9186 WMSFT_SegContents ref_seg
;
9187 WMSFT_SegContents guidhash_seg
;
9188 WMSFT_SegContents guid_seg
;
9189 WMSFT_SegContents namehash_seg
;
9190 WMSFT_SegContents name_seg
;
9191 WMSFT_SegContents string_seg
;
9192 WMSFT_SegContents typdesc_seg
;
9193 WMSFT_SegContents arraydesc_seg
;
9194 WMSFT_SegContents custdata_seg
;
9195 WMSFT_SegContents cdguids_seg
;
9197 WMSFT_SegContents aux_seg
;
9200 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9201 WMSFT_TLBFile
*file
)
9207 file
->string_seg
.len
= 0;
9208 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9211 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9213 return E_UNEXPECTED
;
9215 size
+= sizeof(INT16
);
9217 size
= (size
+ 4) & ~0x3;
9221 file
->string_seg
.len
+= size
;
9223 /* temporarily use str->offset to store the length of the aligned,
9224 * converted string */
9228 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
9231 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9234 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9235 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9237 heap_free(file
->string_seg
.data
);
9238 return E_UNEXPECTED
;
9241 *((INT16
*)data
) = size
;
9243 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9247 str
->offset
= last_offs
;
9254 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9255 WMSFT_TLBFile
*file
)
9260 MSFT_NameIntro
*last_intro
= NULL
;
9262 file
->header
.nametablecount
= 0;
9263 file
->header
.nametablechars
= 0;
9265 file
->name_seg
.len
= 0;
9266 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9269 size
= lstrlenW(str
->str
);
9270 file
->header
.nametablechars
+= size
;
9271 file
->header
.nametablecount
++;
9273 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9275 return E_UNEXPECTED
;
9277 size
+= sizeof(MSFT_NameIntro
);
9279 size
= (size
+ 4) & ~0x3;
9283 file
->name_seg
.len
+= size
;
9285 /* temporarily use str->offset to store the length of the aligned,
9286 * converted string */
9290 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9291 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
9294 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9296 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9298 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9299 data
+ sizeof(MSFT_NameIntro
),
9300 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9302 heap_free(file
->name_seg
.data
);
9303 return E_UNEXPECTED
;
9305 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9307 intro
->hreftype
= -1; /* TODO? */
9308 intro
->namelen
= size
& 0xFF;
9309 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9310 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9311 intro
->namelen
|= hash
<< 16;
9312 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9313 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9315 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9316 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9318 /* update str->offset to actual value to use in other
9319 * compilation functions that require positions within
9320 * the string table */
9324 str
->offset
= last_offs
;
9329 last_intro
->hreftype
= 0; /* last one is 0? */
9334 static inline int hash_guid(GUID
*guid
)
9338 for (i
= 0; i
< 8; i
++)
9339 hash
^= ((const short *)guid
)[i
];
9344 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9347 MSFT_GuidEntry
*entry
;
9349 int hash_key
, *guidhashtab
;
9351 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9352 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9354 entry
= file
->guid_seg
.data
;
9356 guidhashtab
= file
->guidhash_seg
.data
;
9357 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9358 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9359 entry
->hreftype
= guid
->hreftype
;
9361 hash_key
= hash_guid(&guid
->guid
);
9362 entry
->next_hash
= guidhashtab
[hash_key
];
9363 guidhashtab
[hash_key
] = offs
;
9365 guid
->offset
= offs
;
9366 offs
+= sizeof(MSFT_GuidEntry
);
9373 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9376 VARTYPE arg_type
= V_VT(value
);
9379 DWORD ret
= file
->custdata_seg
.len
;
9381 if(arg_type
== VT_INT
)
9383 if(arg_type
== VT_UINT
)
9387 if(V_VT(value
) != arg_type
) {
9388 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9390 ERR("VariantChangeType failed: %08x\n", hres
);
9395 /* Check if default value can be stored in-place */
9400 if(V_UI4(&v
) > 0x3ffffff)
9413 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9416 /* have to allocate space in custdata_seg */
9425 /* Construct the data to be allocated */
9428 if(file
->custdata_seg
.data
){
9429 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9430 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9431 file
->custdata_seg
.len
+= sizeof(int) * 2;
9433 file
->custdata_seg
.len
= sizeof(int) * 2;
9434 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9437 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9438 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9440 /* TODO: Check if the encoded data is already present in custdata_seg */
9446 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9449 if(file
->custdata_seg
.data
){
9450 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9451 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9452 file
->custdata_seg
.len
+= len
;
9454 file
->custdata_seg
.len
= len
;
9455 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9458 *((unsigned short *)data
) = V_VT(value
);
9459 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9460 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9461 if(V_BSTR(&v
)[i
] <= 0x7f)
9462 data
[i
+6] = V_BSTR(&v
)[i
];
9466 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9467 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9470 /* TODO: Check if the encoded data is already present in custdata_seg */
9475 FIXME("Argument type not yet handled\n");
9480 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9482 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9484 DWORD offs
= file
->arraydesc_seg
.len
;
9488 /* TODO: we should check for duplicates, but that's harder because each
9489 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9490 * at the library-level) */
9492 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9493 if(!file
->arraydesc_seg
.data
)
9494 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9496 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9497 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9499 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9500 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9501 for(i
= 0; i
< desc
->cDims
; ++i
){
9502 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9503 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9509 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9515 VARTYPE vt
, subtype
;
9526 vt
= desc
->vt
& VT_TYPEMASK
;
9528 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9530 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9531 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9533 *out_size
+= 2 * sizeof(DWORD
);
9534 }else if(vt
== VT_CARRAY
){
9535 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9536 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9538 }else if(vt
== VT_USERDEFINED
){
9539 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9540 encoded
[1] = desc
->u
.hreftype
;
9541 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9543 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9561 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9564 data
= file
->typdesc_seg
.data
;
9565 while(offs
< file
->typdesc_seg
.len
){
9566 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9568 offs
+= sizeof(encoded
);
9571 file
->typdesc_seg
.len
+= sizeof(encoded
);
9572 if(!file
->typdesc_seg
.data
)
9573 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9575 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9577 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9582 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9584 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9585 DWORD ret
= cdguids_seg
->len
, offs
;
9586 MSFT_CDGuid
*cdguid
;
9589 if(list_empty(custdata_list
))
9592 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9593 if(!cdguids_seg
->data
){
9594 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9596 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9597 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9600 offs
= ret
+ sizeof(MSFT_CDGuid
);
9601 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9602 cdguid
->GuidOffset
= cd
->guid
->offset
;
9603 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9604 cdguid
->next
= offs
;
9605 offs
+= sizeof(MSFT_CDGuid
);
9615 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9616 WMSFT_TLBFile
*file
)
9618 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9619 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9620 MSFT_VarRecord
*varrecord
;
9621 MSFT_FuncRecord
*funcrecord
;
9623 DWORD
*name
, *offsets
, offs
;
9625 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9626 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9628 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9630 /* optional fields */
9631 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9632 if(!list_empty(&desc
->custdata_list
))
9633 recorded_size
+= 7 * sizeof(INT
);
9634 else if(desc
->HelpStringContext
!= 0)
9635 recorded_size
+= 6 * sizeof(INT
);
9637 else if(desc
->Entry
)
9638 recorded_size
+= 3 * sizeof(INT
);
9639 else if(desc
->HelpString
)
9640 recorded_size
+= 2 * sizeof(INT
);
9641 else if(desc
->helpcontext
)
9642 recorded_size
+= sizeof(INT
);
9644 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9646 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9647 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9648 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9653 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9656 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9657 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9659 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9661 /* optional fields */
9662 if(desc
->HelpStringContext
!= 0)
9663 recorded_size
+= 5 * sizeof(INT
);
9664 else if(!list_empty(&desc
->custdata_list
))
9665 recorded_size
+= 4 * sizeof(INT
);
9667 else if(desc
->HelpString
)
9668 recorded_size
+= 2 * sizeof(INT
);
9669 else if(desc
->HelpContext
!= 0)
9670 recorded_size
+= sizeof(INT
);
9672 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9675 if(!recorded_size
&& !extra_size
)
9678 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9680 aux_seg
->len
+= recorded_size
+ extra_size
;
9682 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9685 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9687 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9689 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9691 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9694 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9695 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9696 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9697 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9699 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9700 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9701 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9702 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9705 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9710 * ^has_param_defaults
9711 * ^oEntry_is_intresource
9713 funcrecord
->FKCCIC
=
9714 desc
->funcdesc
.funckind
|
9715 (desc
->funcdesc
.invkind
<< 3) |
9716 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9717 (desc
->funcdesc
.callconv
<< 8);
9719 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9720 funcrecord
->FKCCIC
|= 0x2000;
9722 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9723 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9724 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9725 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9728 if(paramdefault_size
> 0)
9729 funcrecord
->FKCCIC
|= 0x1000;
9731 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9732 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9734 /* optional fields */
9736 if(!list_empty(&desc
->custdata_list
)){
9737 size
+= 7 * sizeof(INT
);
9738 funcrecord
->HelpContext
= desc
->helpcontext
;
9739 if(desc
->HelpString
)
9740 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9742 funcrecord
->oHelpString
= -1;
9744 funcrecord
->oEntry
= -1;
9745 else if(IS_INTRESOURCE(desc
->Entry
))
9746 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9748 funcrecord
->oEntry
= desc
->Entry
->offset
;
9749 funcrecord
->res9
= -1;
9750 funcrecord
->resA
= -1;
9751 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9752 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9753 }else if(desc
->HelpStringContext
!= 0){
9754 size
+= 6 * sizeof(INT
);
9755 funcrecord
->HelpContext
= desc
->helpcontext
;
9756 if(desc
->HelpString
)
9757 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9759 funcrecord
->oHelpString
= -1;
9761 funcrecord
->oEntry
= -1;
9762 else if(IS_INTRESOURCE(desc
->Entry
))
9763 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9765 funcrecord
->oEntry
= desc
->Entry
->offset
;
9766 funcrecord
->res9
= -1;
9767 funcrecord
->resA
= -1;
9768 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9769 }else if(desc
->Entry
){
9770 size
+= 3 * sizeof(INT
);
9771 funcrecord
->HelpContext
= desc
->helpcontext
;
9772 if(desc
->HelpString
)
9773 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9775 funcrecord
->oHelpString
= -1;
9777 funcrecord
->oEntry
= -1;
9778 else if(IS_INTRESOURCE(desc
->Entry
))
9779 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9781 funcrecord
->oEntry
= desc
->Entry
->offset
;
9782 }else if(desc
->HelpString
){
9783 size
+= 2 * sizeof(INT
);
9784 funcrecord
->HelpContext
= desc
->helpcontext
;
9785 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9786 }else if(desc
->helpcontext
){
9787 size
+= sizeof(INT
);
9788 funcrecord
->HelpContext
= desc
->helpcontext
;
9791 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9792 size
+= paramdefault_size
;
9794 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9795 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9797 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9798 if(desc
->pParamDesc
[j
].Name
)
9799 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9802 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9804 if(paramdefault_size
){
9805 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9806 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9807 else if(paramdefault_size
)
9812 size
+= sizeof(MSFT_ParameterInfo
);
9815 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9821 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9824 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9825 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9826 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9827 DWORD size
= 5 * sizeof(INT
);
9829 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9830 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9831 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9832 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9834 if(desc
->vardesc
.varkind
== VAR_CONST
){
9835 varrecord
->vardescsize
+= sizeof(VARIANT
);
9836 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9838 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9841 if(desc
->HelpStringContext
!= 0){
9842 size
+= 5 * sizeof(INT
);
9843 varrecord
->HelpContext
= desc
->HelpContext
;
9844 if(desc
->HelpString
)
9845 varrecord
->HelpString
= desc
->HelpString
->offset
;
9847 varrecord
->HelpString
= -1;
9848 varrecord
->res9
= -1;
9849 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9850 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9851 }else if(!list_empty(&desc
->custdata_list
)){
9852 size
+= 4 * sizeof(INT
);
9853 varrecord
->HelpContext
= desc
->HelpContext
;
9854 if(desc
->HelpString
)
9855 varrecord
->HelpString
= desc
->HelpString
->offset
;
9857 varrecord
->HelpString
= -1;
9858 varrecord
->res9
= -1;
9859 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9860 }else if(desc
->HelpString
){
9861 size
+= 2 * sizeof(INT
);
9862 varrecord
->HelpContext
= desc
->HelpContext
;
9863 if(desc
->HelpString
)
9864 varrecord
->HelpString
= desc
->HelpString
->offset
;
9866 varrecord
->HelpString
= -1;
9867 }else if(desc
->HelpContext
!= 0){
9868 size
+= sizeof(INT
);
9869 varrecord
->HelpContext
= desc
->HelpContext
;
9872 varrecord
->Info
= size
| (i
<< 16);
9878 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9881 memid
= (MEMBERID
*)varrecord
;
9882 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9883 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9884 *memid
= desc
->funcdesc
.memid
;
9887 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9888 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9889 *memid
= desc
->vardesc
.memid
;
9893 name
= (DWORD
*)memid
;
9894 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9895 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9897 *name
= desc
->Name
->offset
;
9902 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9903 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9905 *name
= desc
->Name
->offset
;
9914 typedef struct tagWMSFT_RefChunk
{
9921 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9923 DWORD offs
= file
->ref_seg
.len
, i
;
9924 WMSFT_RefChunk
*chunk
;
9926 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9927 if(!file
->ref_seg
.data
)
9928 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9930 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9932 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9934 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9935 chunk
->href
= info
->impltypes
[i
].hRef
;
9936 chunk
->res04
= info
->impltypes
[i
].implflags
;
9938 if(i
< info
->typeattr
.cImplTypes
- 1)
9939 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9948 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9952 size
= sizeof(MSFT_TypeInfoBase
);
9955 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9956 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9957 base
->typekind
= TKIND_DISPATCH
;
9959 base
->typekind
= info
->typeattr
.typekind
;
9960 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9961 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
9962 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9967 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
9973 base
->posguid
= info
->guid
->offset
;
9976 base
->flags
= info
->typeattr
.wTypeFlags
;
9978 base
->NameOffset
= info
->Name
->offset
;
9980 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9981 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9983 base
->NameOffset
= -1;
9985 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
9987 base
->docstringoffs
= info
->DocString
->offset
;
9989 base
->docstringoffs
= -1;
9990 base
->helpstringcontext
= info
->dwHelpStringContext
;
9991 base
->helpcontext
= info
->dwHelpContext
;
9992 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9993 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
9994 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
9995 base
->size
= info
->typeattr
.cbSizeInstance
;
9996 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
9997 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9998 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
9999 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
10000 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
10002 base
->datatype1
= info
->DllName
->offset
;
10004 base
->datatype1
= -1;
10006 if(info
->typeattr
.cImplTypes
> 0)
10007 base
->datatype1
= info
->impltypes
[0].hRef
;
10009 base
->datatype1
= -1;
10011 base
->datatype2
= index
; /* FIXME: i think there's more here */
10019 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
10023 file
->typeinfo_seg
.len
= 0;
10024 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10025 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
10026 *junk
= file
->typeinfo_seg
.len
;
10028 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
10031 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
10032 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
10034 file
->aux_seg
.len
= 0;
10035 file
->aux_seg
.data
= NULL
;
10037 file
->typeinfo_seg
.len
= 0;
10038 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10039 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
10040 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
10041 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
10045 typedef struct tagWMSFT_ImpFile
{
10051 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10054 WMSFT_ImpFile
*impfile
;
10056 DWORD last_offs
= 0;
10058 file
->impfile_seg
.len
= 0;
10059 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10063 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10067 path
= implib
->name
;
10068 size
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
), NULL
, 0, NULL
, NULL
);
10070 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10073 size
+= sizeof(INT16
);
10075 size
= (size
+ 4) & ~0x3;
10079 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
10082 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
10084 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10085 int strlen
= 0, size
;
10087 impfile
= (WMSFT_ImpFile
*)data
;
10088 impfile
->guid_offs
= implib
->guid
->offset
;
10089 impfile
->lcid
= implib
->lcid
;
10090 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
10092 data
+= sizeof(WMSFT_ImpFile
);
10095 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10099 path
= implib
->name
;
10100 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
),
10101 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
10103 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10106 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
10108 size
= strlen
+ sizeof(INT16
);
10110 size
= (size
+ 4) & ~0x3;
10113 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
10116 implib
->offset
= last_offs
;
10117 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
10121 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10123 MSFT_ImpInfo
*info
;
10124 TLBRefType
*ref_type
;
10127 WMSFT_compile_impfile(This
, file
);
10129 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
10130 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
10132 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
10133 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
10134 if(ref_type
->index
== TLB_REF_USE_GUID
){
10135 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
10136 info
->oGuid
= ref_type
->guid
->offset
;
10138 info
->oGuid
= ref_type
->index
;
10139 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
10145 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10147 file
->guidhash_seg
.len
= 0x80;
10148 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
10149 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
10152 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10154 file
->namehash_seg
.len
= 0x200;
10155 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
10156 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
10159 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
10161 if(contents
&& contents
->len
){
10162 segdir
->offset
= *running_offset
;
10163 segdir
->length
= contents
->len
;
10164 *running_offset
+= segdir
->length
;
10166 segdir
->offset
= -1;
10167 segdir
->length
= 0;
10170 /* TODO: do these ever change? */
10171 segdir
->res08
= -1;
10172 segdir
->res0c
= 0xf;
10175 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10179 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10182 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10186 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10188 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10189 base
->memoffset
+= file_len
;
10196 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10198 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
10199 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
10200 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
10201 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
10202 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
10203 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
10204 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
10205 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
10206 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
10207 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
10208 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
10209 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
10210 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
10211 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
10214 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10216 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10217 WMSFT_TLBFile file
;
10218 DWORD written
, junk_size
, junk_offs
, running_offset
;
10225 TRACE("%p\n", This
);
10227 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10228 if(This
->typeinfos
[i
]->needs_layout
)
10229 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10231 memset(&file
, 0, sizeof(file
));
10233 file
.header
.magic1
= 0x5446534D;
10234 file
.header
.magic2
= 0x00010002;
10235 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10236 file
.header
.lcid2
= This
->set_lcid
;
10237 file
.header
.varflags
= 0x40 | This
->syskind
;
10238 if (This
->HelpFile
)
10239 file
.header
.varflags
|= 0x10;
10240 if (This
->HelpStringDll
)
10241 file
.header
.varflags
|= HELPDLLFLAG
;
10242 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10243 file
.header
.flags
= This
->libflags
;
10244 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10245 file
.header
.helpcontext
= This
->dwHelpContext
;
10246 file
.header
.res44
= 0x20;
10247 file
.header
.res48
= 0x80;
10248 file
.header
.dispatchpos
= This
->dispatch_href
;
10250 WMSFT_compile_namehash(This
, &file
);
10251 /* do name and string compilation to get offsets for other compilations */
10252 hres
= WMSFT_compile_names(This
, &file
);
10254 WMSFT_free_file(&file
);
10258 hres
= WMSFT_compile_strings(This
, &file
);
10260 WMSFT_free_file(&file
);
10264 WMSFT_compile_guidhash(This
, &file
);
10265 hres
= WMSFT_compile_guids(This
, &file
);
10267 WMSFT_free_file(&file
);
10272 file
.header
.helpfile
= This
->HelpFile
->offset
;
10274 file
.header
.helpfile
= -1;
10276 if(This
->DocString
)
10277 file
.header
.helpstring
= This
->DocString
->offset
;
10279 file
.header
.helpstring
= -1;
10281 /* do some more segment compilation */
10282 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10283 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10286 file
.header
.NameOffset
= This
->Name
->offset
;
10288 file
.header
.NameOffset
= -1;
10290 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10293 file
.header
.posguid
= This
->guid
->offset
;
10295 file
.header
.posguid
= -1;
10297 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10298 if(file
.header
.varflags
& HELPDLLFLAG
)
10299 junk_size
+= sizeof(DWORD
);
10301 junk
= heap_alloc_zero(junk_size
);
10302 if(file
.header
.varflags
& HELPDLLFLAG
){
10303 *junk
= This
->HelpStringDll
->offset
;
10312 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10313 WMSFT_compile_impinfo(This
, &file
);
10315 running_offset
= 0;
10317 TRACE("header at: 0x%x\n", running_offset
);
10318 running_offset
+= sizeof(file
.header
);
10320 TRACE("junk at: 0x%x\n", running_offset
);
10321 running_offset
+= junk_size
;
10323 TRACE("segdir at: 0x%x\n", running_offset
);
10324 running_offset
+= sizeof(file
.segdir
);
10326 TRACE("typeinfo at: 0x%x\n", running_offset
);
10327 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10329 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10330 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10332 TRACE("guidtab at: 0x%x\n", running_offset
);
10333 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10335 TRACE("reftab at: 0x%x\n", running_offset
);
10336 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10338 TRACE("impinfo at: 0x%x\n", running_offset
);
10339 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10341 TRACE("impfiles at: 0x%x\n", running_offset
);
10342 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10344 TRACE("namehashtab at: 0x%x\n", running_offset
);
10345 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10347 TRACE("nametab at: 0x%x\n", running_offset
);
10348 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10350 TRACE("stringtab at: 0x%x\n", running_offset
);
10351 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10353 TRACE("typdesc at: 0x%x\n", running_offset
);
10354 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10356 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10357 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10359 TRACE("custdata at: 0x%x\n", running_offset
);
10360 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10362 TRACE("cdguids at: 0x%x\n", running_offset
);
10363 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10365 TRACE("res0e at: 0x%x\n", running_offset
);
10366 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10368 TRACE("res0f at: 0x%x\n", running_offset
);
10369 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10371 TRACE("aux_seg at: 0x%x\n", running_offset
);
10373 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10375 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10376 FILE_ATTRIBUTE_NORMAL
, 0);
10377 if (outfile
== INVALID_HANDLE_VALUE
){
10378 WMSFT_free_file(&file
);
10380 return TYPE_E_IOERROR
;
10383 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10385 WMSFT_free_file(&file
);
10386 CloseHandle(outfile
);
10388 return TYPE_E_IOERROR
;
10391 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10394 WMSFT_free_file(&file
);
10395 CloseHandle(outfile
);
10396 return TYPE_E_IOERROR
;
10399 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10401 WMSFT_free_file(&file
);
10402 CloseHandle(outfile
);
10403 return TYPE_E_IOERROR
;
10406 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10407 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10408 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10409 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10410 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10411 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10412 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10413 WMSFT_write_segment(outfile
, &file
.name_seg
);
10414 WMSFT_write_segment(outfile
, &file
.string_seg
);
10415 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10416 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10417 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10418 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10419 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10421 WMSFT_free_file(&file
);
10423 CloseHandle(outfile
);
10428 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10431 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10432 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10436 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10437 REFGUID guid
, VARIANT
*varVal
)
10439 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10442 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10444 if (!guid
|| !varVal
)
10445 return E_INVALIDARG
;
10447 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10449 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10452 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10453 ULONG helpStringContext
)
10455 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10456 FIXME("%p %u - stub\n", This
, helpStringContext
);
10460 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10463 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10464 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10467 return E_INVALIDARG
;
10469 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10474 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10475 ICreateTypeLib2_fnQueryInterface
,
10476 ICreateTypeLib2_fnAddRef
,
10477 ICreateTypeLib2_fnRelease
,
10478 ICreateTypeLib2_fnCreateTypeInfo
,
10479 ICreateTypeLib2_fnSetName
,
10480 ICreateTypeLib2_fnSetVersion
,
10481 ICreateTypeLib2_fnSetGuid
,
10482 ICreateTypeLib2_fnSetDocString
,
10483 ICreateTypeLib2_fnSetHelpFileName
,
10484 ICreateTypeLib2_fnSetHelpContext
,
10485 ICreateTypeLib2_fnSetLcid
,
10486 ICreateTypeLib2_fnSetLibFlags
,
10487 ICreateTypeLib2_fnSaveAllChanges
,
10488 ICreateTypeLib2_fnDeleteTypeInfo
,
10489 ICreateTypeLib2_fnSetCustData
,
10490 ICreateTypeLib2_fnSetHelpStringContext
,
10491 ICreateTypeLib2_fnSetHelpStringDll
10494 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10495 REFIID riid
, void **object
)
10497 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10499 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10502 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10504 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10506 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10509 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10511 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10513 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10516 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10519 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10521 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10523 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10528 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10531 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10535 TRACE("%p %x\n", This
, typeFlags
);
10537 if (typeFlags
& TYPEFLAG_FDUAL
) {
10539 ITypeInfo
*dispatch
;
10543 hres
= LoadTypeLib(L
"stdole2.tlb", &stdole
);
10547 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10548 ITypeLib_Release(stdole
);
10552 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10553 ITypeInfo_Release(dispatch
);
10558 old_flags
= This
->typeattr
.wTypeFlags
;
10559 This
->typeattr
.wTypeFlags
= typeFlags
;
10561 hres
= ICreateTypeInfo2_LayOut(iface
);
10562 if (FAILED(hres
)) {
10563 This
->typeattr
.wTypeFlags
= old_flags
;
10570 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10573 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10575 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10578 return E_INVALIDARG
;
10580 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10585 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10588 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10590 TRACE("%p %d\n", This
, helpContext
);
10592 This
->dwHelpContext
= helpContext
;
10597 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10598 WORD majorVerNum
, WORD minorVerNum
)
10600 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10602 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10604 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10605 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10610 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10611 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10613 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10615 ITypeLib
*container
;
10616 TLBRefType
*ref_type
;
10618 TYPEATTR
*typeattr
;
10622 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10624 if (!typeInfo
|| !refType
)
10625 return E_INVALIDARG
;
10627 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10631 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10632 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10634 ITypeLib_Release(container
);
10636 *refType
= target
->hreftype
;
10641 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10642 if (FAILED(hres
)) {
10643 ITypeLib_Release(container
);
10647 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10648 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10649 implib
->lcid
== libattr
->lcid
&&
10650 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10651 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10655 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10656 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10658 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10659 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10660 implib
->name
= SysAllocString(our_container
->path
);
10662 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10663 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10665 implib
->name
= NULL
;
10666 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10670 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10671 implib
->lcid
= libattr
->lcid
;
10672 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10673 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10675 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10678 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10679 ITypeLib_Release(container
);
10681 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10686 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10687 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10688 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10689 ref_type
->tkind
== typeattr
->typekind
)
10694 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10695 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10697 ref_type
->tkind
= typeattr
->typekind
;
10698 ref_type
->pImpTLInfo
= implib
;
10699 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10701 ref_type
->index
= TLB_REF_USE_GUID
;
10703 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10705 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10708 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10710 *refType
= ref_type
->reference
| 0x1;
10712 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10713 This
->pTypeLib
->dispatch_href
= *refType
;
10718 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10719 UINT index
, FUNCDESC
*funcDesc
)
10721 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10722 TLBFuncDesc tmp_func_desc
, *func_desc
;
10727 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10729 if (!funcDesc
|| funcDesc
->oVft
& 3)
10730 return E_INVALIDARG
;
10732 switch (This
->typeattr
.typekind
) {
10734 if (funcDesc
->funckind
!= FUNC_STATIC
)
10735 return TYPE_E_BADMODULEKIND
;
10737 case TKIND_DISPATCH
:
10738 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10739 return TYPE_E_BADMODULEKIND
;
10742 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10743 return TYPE_E_BADMODULEKIND
;
10746 if (index
> This
->typeattr
.cFuncs
)
10747 return TYPE_E_ELEMENTNOTFOUND
;
10749 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10750 !funcDesc
->cParams
)
10751 return TYPE_E_INCONSISTENTPROPFUNCS
;
10754 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10755 funcDesc
->oVft
% 8 != 0)
10756 return E_INVALIDARG
;
10759 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10760 TLBFuncDesc_Constructor(&tmp_func_desc
);
10762 tmp_func_desc
.funcdesc
= *funcDesc
;
10764 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10765 tmp_func_desc
.funcdesc
.oVft
|= 1;
10767 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10768 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10769 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10771 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10772 tmp_func_desc
.funcdesc
.cScodes
= 0;
10775 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10776 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10777 buf_size
+= sizeof(ELEMDESC
);
10778 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10780 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10781 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10783 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10784 if (FAILED(hres
)) {
10785 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10786 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10790 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10791 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10792 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10793 if (FAILED(hres
)) {
10794 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10795 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10798 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10799 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10800 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10801 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10802 if (FAILED(hres
)) {
10803 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10804 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10810 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10812 if (This
->funcdescs
) {
10813 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10814 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10816 if (index
< This
->typeattr
.cFuncs
) {
10817 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10818 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10819 func_desc
= This
->funcdescs
+ index
;
10821 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10823 /* move custdata lists to the new memory location */
10824 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10826 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
10829 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10831 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10832 list_init(&func_desc
->custdata_list
);
10834 ++This
->typeattr
.cFuncs
;
10836 This
->needs_layout
= TRUE
;
10841 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10842 UINT index
, HREFTYPE refType
)
10844 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10845 TLBImplType
*impl_type
;
10848 TRACE("%p %u %d\n", This
, index
, refType
);
10850 switch(This
->typeattr
.typekind
){
10851 case TKIND_COCLASS
: {
10853 FIXME("Unhandled index: -1\n");
10857 if(index
!= This
->typeattr
.cImplTypes
)
10858 return TYPE_E_ELEMENTNOTFOUND
;
10862 case TKIND_INTERFACE
:
10863 case TKIND_DISPATCH
:
10864 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10865 return TYPE_E_ELEMENTNOTFOUND
;
10868 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10872 if (This
->impltypes
){
10875 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10876 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10878 if (index
< This
->typeattr
.cImplTypes
) {
10879 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10880 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10881 impl_type
= This
->impltypes
+ index
;
10883 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10885 /* move custdata lists to the new memory location */
10886 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10888 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
10891 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10893 memset(impl_type
, 0, sizeof(TLBImplType
));
10894 TLBImplType_Constructor(impl_type
);
10895 impl_type
->hRef
= refType
;
10897 ++This
->typeattr
.cImplTypes
;
10899 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10900 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10902 hres
= ICreateTypeInfo2_LayOut(iface
);
10909 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10910 UINT index
, INT implTypeFlags
)
10912 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10913 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10915 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10917 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10918 return TYPE_E_BADMODULEKIND
;
10920 if (index
>= This
->typeattr
.cImplTypes
)
10921 return TYPE_E_ELEMENTNOTFOUND
;
10923 impl_type
->implflags
= implTypeFlags
;
10928 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10931 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10933 TRACE("%p %d\n", This
, alignment
);
10935 This
->typeattr
.cbAlignment
= alignment
;
10940 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10943 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10945 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10948 return E_INVALIDARG
;
10950 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10952 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10957 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10958 UINT index
, VARDESC
*varDesc
)
10960 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10961 TLBVarDesc
*var_desc
;
10964 TRACE("%p %u %p\n", This
, index
, varDesc
);
10966 if (This
->vardescs
){
10969 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10970 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
10972 if (index
< This
->typeattr
.cVars
) {
10973 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10974 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
10975 var_desc
= This
->vardescs
+ index
;
10977 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
10979 /* move custdata lists to the new memory location */
10980 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
10982 TLB_relink_custdata(&This
->vardescs
[i
].custdata_list
);
10985 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10987 TLBVarDesc_Constructor(var_desc
);
10988 hr
= TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10991 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10993 ++This
->typeattr
.cVars
;
10995 This
->needs_layout
= TRUE
;
11000 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
11001 UINT index
, LPOLESTR
*names
, UINT numNames
)
11003 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11004 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11007 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
11010 return E_INVALIDARG
;
11012 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
11013 return TYPE_E_ELEMENTNOTFOUND
;
11015 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
11016 if(numNames
> func_desc
->funcdesc
.cParams
)
11017 return TYPE_E_ELEMENTNOTFOUND
;
11019 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
11020 return TYPE_E_ELEMENTNOTFOUND
;
11022 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
11023 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
11024 if (iter
->Name
&& !wcscmp(TLB_get_bstr(iter
->Name
), *names
)) {
11025 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
11026 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
11027 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
11029 return TYPE_E_AMBIGUOUSNAME
;
11033 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
11035 for (i
= 1; i
< numNames
; ++i
) {
11036 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
11037 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
11043 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
11044 UINT index
, LPOLESTR name
)
11046 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11048 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
11051 return E_INVALIDARG
;
11053 if(index
>= This
->typeattr
.cVars
)
11054 return TYPE_E_ELEMENTNOTFOUND
;
11056 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11060 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
11061 TYPEDESC
*tdescAlias
)
11063 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11066 TRACE("%p %p\n", This
, tdescAlias
);
11069 return E_INVALIDARG
;
11071 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
11072 return TYPE_E_BADMODULEKIND
;
11074 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
11078 heap_free(This
->tdescAlias
);
11079 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
11080 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
11085 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
11086 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
11088 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11089 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
11093 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
11094 UINT index
, LPOLESTR docString
)
11096 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11097 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11099 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11102 return E_INVALIDARG
;
11104 if(index
>= This
->typeattr
.cFuncs
)
11105 return TYPE_E_ELEMENTNOTFOUND
;
11107 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11112 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
11113 UINT index
, LPOLESTR docString
)
11115 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11116 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11118 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11121 return E_INVALIDARG
;
11123 if(index
>= This
->typeattr
.cVars
)
11124 return TYPE_E_ELEMENTNOTFOUND
;
11126 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11131 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
11132 UINT index
, DWORD helpContext
)
11134 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11135 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11137 TRACE("%p %u %d\n", This
, index
, helpContext
);
11139 if(index
>= This
->typeattr
.cFuncs
)
11140 return TYPE_E_ELEMENTNOTFOUND
;
11142 func_desc
->helpcontext
= helpContext
;
11147 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
11148 UINT index
, DWORD helpContext
)
11150 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11151 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11153 TRACE("%p %u %d\n", This
, index
, helpContext
);
11155 if(index
>= This
->typeattr
.cVars
)
11156 return TYPE_E_ELEMENTNOTFOUND
;
11158 var_desc
->HelpContext
= helpContext
;
11163 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
11164 UINT index
, BSTR bstrMops
)
11166 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11167 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
11171 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
11174 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11176 TRACE("%p %p\n", This
, idlDesc
);
11179 return E_INVALIDARG
;
11181 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11182 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11187 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11189 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11190 ITypeInfo2
*tinfo
= &This
->ITypeInfo2_iface
;
11191 TLBFuncDesc
*func_desc
;
11192 UINT user_vft
= 0, i
, depth
= 0;
11193 HRESULT hres
= S_OK
;
11195 TRACE("%p\n", This
);
11197 This
->needs_layout
= FALSE
;
11199 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11204 hres
= ITypeInfo2_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11206 if (SUCCEEDED(hres
)) {
11207 hres
= ITypeInfo2_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11209 if (SUCCEEDED(hres
)) {
11210 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11211 if (FAILED(hres
)) {
11212 ITypeInfo_Release(inh
);
11215 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11216 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11220 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11221 if(SUCCEEDED(hres
)){
11223 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11224 if(SUCCEEDED(hres
)){
11225 ITypeInfo_Release(inh
);
11229 }while(SUCCEEDED(hres
));
11232 ITypeInfo_Release(inh
);
11233 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11234 This
->typeattr
.cbSizeVft
= 0;
11238 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11239 This
->typeattr
.cbSizeVft
= 0;
11243 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11244 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11246 This
->typeattr
.cbSizeVft
= 0;
11248 func_desc
= This
->funcdescs
;
11250 while (i
< This
->typeattr
.cFuncs
) {
11251 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11252 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11254 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11255 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11257 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11259 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11262 BOOL reset
= FALSE
;
11264 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11266 iter
= This
->funcdescs
;
11267 while (j
< This
->typeattr
.cFuncs
) {
11268 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11270 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11273 ++func_desc
->funcdesc
.memid
;
11274 iter
= This
->funcdescs
;
11287 if (user_vft
> This
->typeattr
.cbSizeVft
)
11288 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11290 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11291 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11292 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11294 BOOL reset
= FALSE
;
11297 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11299 iter
= This
->vardescs
;
11300 while (j
< This
->typeattr
.cVars
) {
11301 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11303 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11306 ++var_desc
->vardesc
.memid
;
11307 iter
= This
->vardescs
;
11320 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11323 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11326 TRACE("%p %u\n", This
, index
);
11328 if (index
>= This
->typeattr
.cFuncs
)
11329 return TYPE_E_ELEMENTNOTFOUND
;
11331 typeinfo_release_funcdesc(&This
->funcdescs
[index
]);
11333 --This
->typeattr
.cFuncs
;
11334 if (index
!= This
->typeattr
.cFuncs
)
11336 memmove(This
->funcdescs
+ index
, This
->funcdescs
+ index
+ 1,
11337 sizeof(*This
->funcdescs
) * (This
->typeattr
.cFuncs
- index
));
11338 for (i
= index
; i
< This
->typeattr
.cFuncs
; ++i
)
11339 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
11342 This
->needs_layout
= TRUE
;
11347 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11348 MEMBERID memid
, INVOKEKIND invKind
)
11350 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11351 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11355 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11358 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11359 FIXME("%p %u - stub\n", This
, index
);
11363 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11366 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11367 FIXME("%p %x - stub\n", This
, memid
);
11371 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11374 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11377 TRACE("%p %u\n", This
, index
);
11379 if (index
>= This
->typeattr
.cImplTypes
)
11380 return TYPE_E_ELEMENTNOTFOUND
;
11382 TLB_FreeCustData(&This
->impltypes
[index
].custdata_list
);
11383 --This
->typeattr
.cImplTypes
;
11385 if (index
< This
->typeattr
.cImplTypes
)
11387 memmove(This
->impltypes
+ index
, This
->impltypes
+ index
+ 1, (This
->typeattr
.cImplTypes
- index
) *
11388 sizeof(*This
->impltypes
));
11389 for (i
= index
; i
< This
->typeattr
.cImplTypes
; ++i
)
11390 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
11396 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11397 REFGUID guid
, VARIANT
*varVal
)
11401 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11403 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11405 if (!guid
|| !varVal
)
11406 return E_INVALIDARG
;
11408 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11410 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11413 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11414 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11416 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11417 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11421 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11422 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11424 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11425 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11429 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11430 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11432 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11433 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11437 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11438 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11440 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11441 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11445 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11446 ULONG helpStringContext
)
11448 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11450 TRACE("%p %u\n", This
, helpStringContext
);
11452 This
->dwHelpStringContext
= helpStringContext
;
11457 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11458 UINT index
, ULONG helpStringContext
)
11460 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11461 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11465 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11466 UINT index
, ULONG helpStringContext
)
11468 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11469 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11473 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11475 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11476 FIXME("%p - stub\n", This
);
11480 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11483 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11485 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11488 return E_INVALIDARG
;
11490 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11495 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11496 ICreateTypeInfo2_fnQueryInterface
,
11497 ICreateTypeInfo2_fnAddRef
,
11498 ICreateTypeInfo2_fnRelease
,
11499 ICreateTypeInfo2_fnSetGuid
,
11500 ICreateTypeInfo2_fnSetTypeFlags
,
11501 ICreateTypeInfo2_fnSetDocString
,
11502 ICreateTypeInfo2_fnSetHelpContext
,
11503 ICreateTypeInfo2_fnSetVersion
,
11504 ICreateTypeInfo2_fnAddRefTypeInfo
,
11505 ICreateTypeInfo2_fnAddFuncDesc
,
11506 ICreateTypeInfo2_fnAddImplType
,
11507 ICreateTypeInfo2_fnSetImplTypeFlags
,
11508 ICreateTypeInfo2_fnSetAlignment
,
11509 ICreateTypeInfo2_fnSetSchema
,
11510 ICreateTypeInfo2_fnAddVarDesc
,
11511 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11512 ICreateTypeInfo2_fnSetVarName
,
11513 ICreateTypeInfo2_fnSetTypeDescAlias
,
11514 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11515 ICreateTypeInfo2_fnSetFuncDocString
,
11516 ICreateTypeInfo2_fnSetVarDocString
,
11517 ICreateTypeInfo2_fnSetFuncHelpContext
,
11518 ICreateTypeInfo2_fnSetVarHelpContext
,
11519 ICreateTypeInfo2_fnSetMops
,
11520 ICreateTypeInfo2_fnSetTypeIdldesc
,
11521 ICreateTypeInfo2_fnLayOut
,
11522 ICreateTypeInfo2_fnDeleteFuncDesc
,
11523 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11524 ICreateTypeInfo2_fnDeleteVarDesc
,
11525 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11526 ICreateTypeInfo2_fnDeleteImplType
,
11527 ICreateTypeInfo2_fnSetCustData
,
11528 ICreateTypeInfo2_fnSetFuncCustData
,
11529 ICreateTypeInfo2_fnSetParamCustData
,
11530 ICreateTypeInfo2_fnSetVarCustData
,
11531 ICreateTypeInfo2_fnSetImplTypeCustData
,
11532 ICreateTypeInfo2_fnSetHelpStringContext
,
11533 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11534 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11535 ICreateTypeInfo2_fnInvalidate
,
11536 ICreateTypeInfo2_fnSetName
11539 /******************************************************************************
11540 * ClearCustData (OLEAUT32.171)
11542 * Clear a custom data type's data.
11545 * lpCust [I] The custom data type instance
11550 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11552 if (lpCust
&& lpCust
->cCustData
)
11554 if (lpCust
->prgCustData
)
11558 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11559 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11561 CoTaskMemFree(lpCust
->prgCustData
);
11562 lpCust
->prgCustData
= NULL
;
11564 lpCust
->cCustData
= 0;