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
51 #include "wine/port.h"
60 #define NONAMELESSUNION
61 #define NONAMELESSSTRUCT
72 #include "wine/unicode.h"
75 #include "wine/debug.h"
77 #include "wine/list.h"
79 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
80 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
94 WORD type_id
; /* Type identifier */
95 WORD count
; /* Number of resources of this type */
96 DWORD resloader
; /* SetResourceHandler() */
102 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
103 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
104 static void TLB_FreeVarDesc(VARDESC
*);
106 /****************************************************************************
109 * Takes p_iVal (which is in little endian) and returns it
110 * in the host machine's byte order.
112 #ifdef WORDS_BIGENDIAN
113 static WORD
FromLEWord(WORD p_iVal
)
115 return (((p_iVal
& 0x00FF) << 8) |
116 ((p_iVal
& 0xFF00) >> 8));
120 static DWORD
FromLEDWord(DWORD p_iVal
)
122 return (((p_iVal
& 0x000000FF) << 24) |
123 ((p_iVal
& 0x0000FF00) << 8) |
124 ((p_iVal
& 0x00FF0000) >> 8) |
125 ((p_iVal
& 0xFF000000) >> 24));
128 #define FromLEWord(X) (X)
129 #define FromLEDWord(X) (X)
132 #define DISPATCH_HREF_OFFSET 0x01000000
133 #define DISPATCH_HREF_MASK 0xff000000
135 /****************************************************************************
138 * Fix byte order in any structure if necessary
140 #ifdef WORDS_BIGENDIAN
141 static void FromLEWords(void *p_Val
, int p_iSize
)
145 p_iSize
/= sizeof(WORD
);
148 *Val
= FromLEWord(*Val
);
155 static void FromLEDWords(void *p_Val
, int p_iSize
)
159 p_iSize
/= sizeof(DWORD
);
162 *Val
= FromLEDWord(*Val
);
168 #define FromLEWords(X,Y) /*nothing*/
169 #define FromLEDWords(X,Y) /*nothing*/
173 * Find a typelib key which matches a requested maj.min version.
175 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
177 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
181 INT best_maj
= -1, best_min
= -1;
184 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
185 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
187 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
190 len
= sizeof(key_name
);
192 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
196 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
198 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
200 if (*wMaj
== 0xffff && *wMin
== 0xffff)
202 if (v_maj
> best_maj
) best_maj
= v_maj
;
203 if (v_min
> best_min
) best_min
= v_min
;
205 else if (*wMaj
== v_maj
)
212 break; /* exact match */
214 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
217 len
= sizeof(key_name
);
221 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
223 if (*wMaj
== 0xffff && *wMin
== 0xffff)
225 if (best_maj
>= 0 && best_min
>= 0)
233 if (*wMaj
== best_maj
&& best_min
>= 0)
241 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
242 /* buffer must be at least 60 characters long */
243 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
245 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
246 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
248 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
249 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
250 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
254 /* get the path of an interface key, in the form "Interface\\<guid>" */
255 /* buffer must be at least 50 characters long */
256 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
258 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
260 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
261 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
265 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
266 /* buffer must be at least 16 characters long */
267 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
269 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
270 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
271 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
272 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
274 sprintfW( buffer
, LcidFormatW
, lcid
);
277 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
278 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
279 case SYS_WIN64
: strcatW( buffer
, win64W
); break;
281 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
287 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
289 struct tlibredirect_data
303 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
304 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
305 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
307 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
311 WCHAR Path
[MAX_PATH
];
314 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
318 ACTCTX_SECTION_KEYED_DATA data
;
320 data
.cbSize
= sizeof(data
);
321 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
323 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
327 if (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
)
328 return TYPE_E_LIBNOTREGISTERED
;
330 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
331 len
= SearchPathW( NULL
, nameW
, NULL
, sizeof(Path
)/sizeof(WCHAR
), Path
, NULL
);
332 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
334 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
335 *path
= SysAllocString( Path
);
340 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
341 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
343 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
344 if (res
== ERROR_FILE_NOT_FOUND
)
346 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
347 return TYPE_E_LIBNOTREGISTERED
;
349 else if (res
!= ERROR_SUCCESS
)
351 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
352 return TYPE_E_REGISTRYACCESS
;
357 LONG dwPathLen
= sizeof(Path
);
359 get_lcid_subkey( myLCID
, syskind
, buffer
);
361 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
365 else if (myLCID
== lcid
)
367 /* try with sub-langid */
368 myLCID
= SUBLANGID(lcid
);
370 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
372 /* try with system langid */
382 *path
= SysAllocString( Path
);
387 TRACE_(typelib
)("-- 0x%08x\n", hr
);
391 /****************************************************************************
392 * QueryPathOfRegTypeLib [OLEAUT32.164]
394 * Gets the path to a registered type library.
397 * guid [I] referenced guid
398 * wMaj [I] major version
399 * wMin [I] minor version
401 * path [O] path of typelib
405 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
406 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
409 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
413 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
418 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
421 /******************************************************************************
422 * CreateTypeLib [OLEAUT32.160] creates a typelib
428 HRESULT WINAPI
CreateTypeLib(
429 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
431 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
435 /******************************************************************************
436 * LoadTypeLib [OLEAUT32.161]
438 * Loads a type library
441 * szFile [I] Name of file to load from.
442 * pptLib [O] Pointer that receives ITypeLib object on success.
449 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
451 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
453 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
454 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
457 /******************************************************************************
458 * LoadTypeLibEx [OLEAUT32.183]
460 * Loads and optionally registers a type library
466 HRESULT WINAPI
LoadTypeLibEx(
467 LPCOLESTR szFile
, /* [in] Name of file to load from */
468 REGKIND regkind
, /* [in] Specify kind of registration */
469 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
471 WCHAR szPath
[MAX_PATH
+1];
474 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
478 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
483 case REGKIND_DEFAULT
:
484 /* don't register typelibs supplied with full path. Experimentation confirms the following */
485 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
486 (szFile
[0] && (szFile
[1] == ':'))) break;
487 /* else fall-through */
489 case REGKIND_REGISTER
:
490 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
492 ITypeLib_Release(*pptLib
);
500 TRACE(" returns %08x\n",res
);
504 /******************************************************************************
505 * LoadRegTypeLib [OLEAUT32.162]
507 * Loads a registered type library.
510 * rguid [I] GUID of the registered type library.
511 * wVerMajor [I] major version.
512 * wVerMinor [I] minor version.
513 * lcid [I] locale ID.
514 * ppTLib [O] pointer that receives an ITypeLib object on success.
518 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
521 HRESULT WINAPI
LoadRegTypeLib(
533 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
537 res
= LoadTypeLib(bstr
, ppTLib
);
544 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
545 if (res
== S_OK
&& (attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
))
547 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
548 ITypeLib_Release(*ppTLib
);
550 res
= TYPE_E_LIBNOTREGISTERED
;
555 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
561 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
562 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
563 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
564 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
565 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
566 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
568 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
573 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
574 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
575 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
577 get_interface_key( &tattr
->guid
, keyName
);
578 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
579 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
582 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
583 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
585 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
586 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
587 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
588 (const BYTE
*)PSOA
, sizeof PSOA
);
592 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
593 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
594 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
595 (const BYTE
*)PSOA
, sizeof PSOA
);
599 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
600 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
603 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
604 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
606 StringFromGUID2(&libattr
->guid
, buffer
, 40);
607 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
608 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
609 sprintfW(buffer
, fmtver
, libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
610 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
611 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
619 /******************************************************************************
620 * RegisterTypeLib [OLEAUT32.163]
621 * Adds information about a type library to the System Registry
623 * Docs: ITypeLib FAR * ptlib
624 * Docs: OLECHAR FAR* szFullPath
625 * Docs: OLECHAR FAR* szHelpDir
631 HRESULT WINAPI
RegisterTypeLib(
632 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
633 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
634 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
646 if (ptlib
== NULL
|| szFullPath
== NULL
)
649 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
653 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
656 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
659 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
660 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
664 /* Set the human-readable name of the typelib */
665 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
669 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
670 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
676 /* Make up the name of the typelib path subkey */
677 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
679 /* Create the typelib path subkey */
680 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
681 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
683 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
684 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
692 /* Create the flags subkey */
693 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
694 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
696 /* FIXME: is %u correct? */
697 static const WCHAR formatW
[] = {'%','u',0};
699 sprintfW(buf
, formatW
, attr
->wLibFlags
);
700 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
701 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
709 /* create the helpdir subkey */
710 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
711 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
713 BOOL freeHelpDir
= FALSE
;
716 /* if we created a new key, and helpDir was null, set the helpdir
717 to the directory which contains the typelib. However,
718 if we just opened an existing key, we leave the helpdir alone */
719 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
720 szHelpDir
= SysAllocString(szFullPath
);
721 pIndexStr
= strrchrW(szHelpDir
, '\\');
728 /* if we have an szHelpDir, set it! */
729 if (szHelpDir
!= NULL
) {
730 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
731 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
737 if (freeHelpDir
) SysFreeString(szHelpDir
);
749 /* register OLE Automation-compatible interfaces for this typelib */
750 types
= ITypeLib_GetTypeInfoCount(ptlib
);
751 for (tidx
=0; tidx
<types
; tidx
++) {
752 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
753 LPOLESTR name
= NULL
;
754 ITypeInfo
*tinfo
= NULL
;
756 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
759 case TKIND_INTERFACE
:
760 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
761 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
765 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
766 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
770 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
775 TYPEATTR
*tattr
= NULL
;
776 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
779 TRACE_(typelib
)("guid=%s, flags=%04x (",
780 debugstr_guid(&tattr
->guid
),
783 if (TRACE_ON(typelib
)) {
784 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
804 /* Register all dispinterfaces (which includes dual interfaces) and
805 oleautomation interfaces */
806 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
807 kind
== TKIND_DISPATCH
)
810 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
812 /* register interface<->typelib coupling */
813 TLB_register_interface(attr
, name
, tattr
, 0);
815 /* register TLBs into the opposite registry view, too */
816 if(opposite
== KEY_WOW64_32KEY
||
817 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
818 TLB_register_interface(attr
, name
, tattr
, opposite
);
821 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
824 ITypeInfo_Release(tinfo
);
831 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
837 /******************************************************************************
838 * UnRegisterTypeLib [OLEAUT32.186]
839 * Removes information about a type library from the System Registry
846 HRESULT WINAPI
UnRegisterTypeLib(
847 REFGUID libid
, /* [in] Guid of the library */
848 WORD wVerMajor
, /* [in] major version */
849 WORD wVerMinor
, /* [in] minor version */
850 LCID lcid
, /* [in] locale id */
853 BSTR tlibPath
= NULL
;
856 WCHAR subKeyName
[50];
859 BOOL deleteOtherStuff
;
862 TYPEATTR
* typeAttr
= NULL
;
864 ITypeInfo
* typeInfo
= NULL
;
865 ITypeLib
* typeLib
= NULL
;
868 TRACE("(IID: %s)\n",debugstr_guid(libid
));
870 /* Create the path to the key */
871 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
873 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
875 TRACE("Unsupported syskind %i\n", syskind
);
876 result
= E_INVALIDARG
;
880 /* get the path to the typelib on disk */
881 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
882 result
= E_INVALIDARG
;
886 /* Try and open the key to the type library. */
887 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
888 result
= E_INVALIDARG
;
892 /* Try and load the type library */
893 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
894 result
= TYPE_E_INVALIDSTATE
;
898 /* remove any types registered with this typelib */
899 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
900 for (i
=0; i
<numTypes
; i
++) {
901 /* get the kind of type */
902 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
906 /* skip non-interfaces, and get type info for the type */
907 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
910 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
913 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
917 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
918 kind
== TKIND_DISPATCH
)
920 /* the path to the type */
921 get_interface_key( &typeAttr
->guid
, subKeyName
);
923 /* Delete its bits */
924 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != ERROR_SUCCESS
)
927 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
928 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
929 RegDeleteKeyW(subKey
, TypeLibW
);
932 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
936 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
938 if (typeInfo
) ITypeInfo_Release(typeInfo
);
942 /* Now, delete the type library path subkey */
943 get_lcid_subkey( lcid
, syskind
, subKeyName
);
944 RegDeleteKeyW(key
, subKeyName
);
945 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
946 RegDeleteKeyW(key
, subKeyName
);
948 /* check if there is anything besides the FLAGS/HELPDIR keys.
949 If there is, we don't delete them */
950 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
951 deleteOtherStuff
= TRUE
;
953 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
954 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
956 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
957 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
958 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
959 deleteOtherStuff
= FALSE
;
963 /* only delete the other parts of the key if we're absolutely sure */
964 if (deleteOtherStuff
) {
965 RegDeleteKeyW(key
, FLAGSW
);
966 RegDeleteKeyW(key
, HELPDIRW
);
970 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
971 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
972 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
976 SysFreeString(tlibPath
);
977 if (typeLib
) ITypeLib_Release(typeLib
);
978 if (subKey
) RegCloseKey(subKey
);
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 MEMBERID memidConstructor
;
1221 MEMBERID memidDestructor
;
1222 LPOLESTR lpstrSchema
;
1223 ULONG cbSizeInstance
;
1233 TYPEDESC
*tdescAlias
;
1234 IDLDESC idldescType
;
1236 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1237 int index
; /* index in this typelib; */
1238 HREFTYPE hreftype
; /* hreftype for app object binding */
1239 /* type libs seem to store the doc strings in ascii
1240 * so why should we do it in unicode?
1242 const TLBString
*Name
;
1243 const TLBString
*DocString
;
1244 const TLBString
*DllName
;
1245 const TLBString
*Schema
;
1246 DWORD dwHelpContext
;
1247 DWORD dwHelpStringContext
;
1250 TLBFuncDesc
*funcdescs
;
1253 TLBVarDesc
*vardescs
;
1255 /* Implemented Interfaces */
1256 TLBImplType
*impltypes
;
1258 struct list
*pcustdata_list
;
1259 struct list custdata_list
;
1262 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1264 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1267 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1269 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1272 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1274 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1277 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1279 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1282 static const ITypeInfo2Vtbl tinfvt
;
1283 static const ITypeCompVtbl tcompvt
;
1284 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1286 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1287 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1289 typedef struct tagTLBContext
1291 unsigned int oStart
; /* start of TLB in file */
1292 unsigned int pos
; /* current pos */
1293 unsigned int length
; /* total length */
1294 void *mapping
; /* memory mapping */
1295 MSFT_SegDir
* pTblDir
;
1296 ITypeLibImpl
* pLibInfo
;
1300 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1302 return str
!= NULL
? str
->str
: NULL
;
1305 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1309 return memcmp(left
, str
->str
, len
);
1312 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1314 return guid
!= NULL
? &guid
->guid
: NULL
;
1317 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1319 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1322 static int get_ptr_size(SYSKIND syskind
)
1332 WARN("Unhandled syskind: 0x%x\n", syskind
);
1339 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1340 if (pTD
->vt
& VT_RESERVED
)
1341 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1342 if (pTD
->vt
& VT_BYREF
)
1343 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1344 if (pTD
->vt
& VT_ARRAY
)
1345 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1346 if (pTD
->vt
& VT_VECTOR
)
1347 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1348 switch(pTD
->vt
& VT_TYPEMASK
) {
1349 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1350 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1351 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1352 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1353 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1354 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1355 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1356 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1357 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1358 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1359 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1360 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1361 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1362 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1363 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1364 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1365 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1366 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1367 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1368 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1369 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1370 pTD
->u
.hreftype
); break;
1371 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1372 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1373 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1374 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1376 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1377 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1379 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1380 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1381 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1384 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1388 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1390 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1391 dump_TypeDesc(&edesc
->tdesc
,buf
);
1392 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1393 MESSAGE("\t\tu.paramdesc.wParamFlags");
1394 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1395 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1396 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1397 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1398 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1399 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1400 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1401 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1402 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1404 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1406 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1407 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1408 MESSAGE("Param %d:\n",i
);
1409 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1411 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1412 switch (funcdesc
->funckind
) {
1413 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1414 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1415 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1416 case FUNC_STATIC
: MESSAGE("static");break;
1417 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1418 default: MESSAGE("unknown");break;
1420 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1421 switch (funcdesc
->invkind
) {
1422 case INVOKE_FUNC
: MESSAGE("func");break;
1423 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1424 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1425 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1427 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1428 switch (funcdesc
->callconv
) {
1429 case CC_CDECL
: MESSAGE("cdecl");break;
1430 case CC_PASCAL
: MESSAGE("pascal");break;
1431 case CC_STDCALL
: MESSAGE("stdcall");break;
1432 case CC_SYSCALL
: MESSAGE("syscall");break;
1435 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1436 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1437 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1439 MESSAGE("\telemdescFunc (return value type):\n");
1440 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1443 static const char * const typekind_desc
[] =
1456 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1459 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1460 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1461 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1464 dump_FUNCDESC(&(pfd
->funcdesc
));
1466 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1467 if(pfd
->Entry
== NULL
)
1468 MESSAGE("\tentry: (null)\n");
1469 else if(pfd
->Entry
== (void*)-1)
1470 MESSAGE("\tentry: invalid\n");
1471 else if(IS_INTRESOURCE(pfd
->Entry
))
1472 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1474 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1476 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1480 dump_TLBFuncDescOne(pfd
);
1485 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1489 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1495 static void dump_TLBImpLib(const TLBImpLib
*import
)
1497 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1498 debugstr_w(import
->name
));
1499 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1500 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1503 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1507 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1509 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1510 if(ref
->index
== -1)
1511 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1513 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1515 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1517 TRACE_(typelib
)("in lib\n");
1518 dump_TLBImpLib(ref
->pImpTLInfo
);
1523 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1528 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1529 impl
->hRef
, impl
->implflags
);
1535 static void dump_Variant(const VARIANT
* pvar
)
1539 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1543 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1544 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1546 TRACE(",%p", V_BYREF(pvar
));
1548 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1550 TRACE(",%p", V_ARRAY(pvar
));
1552 else switch (V_TYPE(pvar
))
1554 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1555 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1556 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1557 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1559 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1561 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1562 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1563 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1564 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1565 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1566 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1567 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1568 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1569 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1570 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1571 V_CY(pvar
).s
.Lo
); break;
1573 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1574 TRACE(",<invalid>");
1576 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1577 st
.wHour
, st
.wMinute
, st
.wSecond
);
1581 case VT_USERDEFINED
:
1583 case VT_NULL
: break;
1584 default: TRACE(",?"); break;
1590 static void dump_DispParms(const DISPPARAMS
* pdp
)
1594 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1596 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1598 TRACE("named args:\n");
1599 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1600 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1603 if (pdp
->cArgs
&& pdp
->rgvarg
)
1606 for (index
= 0; index
< pdp
->cArgs
; index
++)
1607 dump_Variant( &pdp
->rgvarg
[index
] );
1611 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1613 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1614 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1615 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1616 TRACE("kind:%s\n", typekind_desc
[pty
->typekind
]);
1617 TRACE("fct:%u var:%u impl:%u\n", pty
->cFuncs
, pty
->cVars
, pty
->cImplTypes
);
1618 TRACE("wTypeFlags: 0x%04x\n", pty
->wTypeFlags
);
1619 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1620 if (pty
->typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1622 dump_TLBFuncDesc(pty
->funcdescs
, pty
->cFuncs
);
1623 dump_TLBVarDesc(pty
->vardescs
, pty
->cVars
);
1624 dump_TLBImplType(pty
->impltypes
, pty
->cImplTypes
);
1627 static void dump_VARDESC(const VARDESC
*v
)
1629 MESSAGE("memid %d\n",v
->memid
);
1630 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1631 MESSAGE("oInst %d\n",v
->u
.oInst
);
1632 dump_ELEMDESC(&(v
->elemdescVar
));
1633 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1634 MESSAGE("varkind %d\n",v
->varkind
);
1637 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1639 /* VT_LPWSTR is largest type that, may appear in type description */
1640 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1641 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1642 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1643 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1644 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1645 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1646 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1647 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1650 static void TLB_abort(void)
1655 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1657 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1658 if (!ret
) ERR("cannot allocate memory\n");
1662 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1664 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1665 if (!ret
) ERR("cannot allocate memory\n");
1669 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1671 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1674 void heap_free(void *ptr
)
1676 HeapFree(GetProcessHeap(), 0, ptr
);
1679 /* returns the size required for a deep copy of a typedesc into a
1681 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1685 if (alloc_initial_space
)
1686 size
+= sizeof(TYPEDESC
);
1692 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1695 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1696 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1702 /* deep copy a typedesc into a flat buffer */
1703 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1708 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1717 dest
->u
.lptdesc
= buffer
;
1718 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1721 dest
->u
.lpadesc
= buffer
;
1722 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1723 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1724 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1730 /* free custom data allocated by MSFT_CustData */
1731 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1733 TLBCustData
*cd
, *cdn
;
1734 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1736 list_remove(&cd
->entry
);
1737 VariantClear(&cd
->data
);
1742 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1747 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1748 ret
= SysAllocStringLen(NULL
, len
- 1);
1749 if (!ret
) return ret
;
1750 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1754 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1755 UINT n
, MEMBERID memid
)
1758 if(funcdescs
->funcdesc
.memid
== memid
)
1766 static inline TLBFuncDesc
*TLB_get_funcdesc_by_name(TLBFuncDesc
*funcdescs
,
1767 UINT n
, const OLECHAR
*name
)
1770 if(!lstrcmpiW(TLB_get_bstr(funcdescs
->Name
), name
))
1778 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1779 UINT n
, MEMBERID memid
)
1782 if(vardescs
->vardesc
.memid
== memid
)
1790 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1791 UINT n
, const OLECHAR
*name
)
1794 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1802 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1804 TLBCustData
*cust_data
;
1805 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1806 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1811 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1812 UINT n
, const OLECHAR
*name
)
1815 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1823 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1825 list_init(&var_desc
->custdata_list
);
1828 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1832 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1837 TLBVarDesc_Constructor(&ret
[n
-1]);
1844 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1848 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1853 list_init(&ret
[n
-1].custdata_list
);
1860 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1862 list_init(&func_desc
->custdata_list
);
1865 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1869 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1874 TLBFuncDesc_Constructor(&ret
[n
-1]);
1881 static void TLBImplType_Constructor(TLBImplType
*impl
)
1883 list_init(&impl
->custdata_list
);
1886 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1890 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1895 TLBImplType_Constructor(&ret
[n
-1]);
1902 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1903 const GUID
*new_guid
, HREFTYPE hreftype
)
1907 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1908 if (IsEqualGUID(&guid
->guid
, new_guid
))
1912 guid
= heap_alloc(sizeof(TLBGuid
));
1916 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1917 guid
->hreftype
= hreftype
;
1919 list_add_tail(guid_list
, &guid
->entry
);
1924 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1926 TLBCustData
*cust_data
;
1938 return DISP_E_BADVARTYPE
;
1941 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1944 cust_data
= heap_alloc(sizeof(TLBCustData
));
1946 return E_OUTOFMEMORY
;
1948 cust_data
->guid
= tlbguid
;
1949 VariantInit(&cust_data
->data
);
1951 list_add_tail(custdata_list
, &cust_data
->entry
);
1953 VariantClear(&cust_data
->data
);
1955 return VariantCopy(&cust_data
->data
, var
);
1958 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1965 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1966 if (strcmpW(str
->str
, new_str
) == 0)
1970 str
= heap_alloc(sizeof(TLBString
));
1974 str
->str
= SysAllocString(new_str
);
1980 list_add_tail(string_list
, &str
->entry
);
1985 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1986 ULONG
*size
, WORD
*align
)
1992 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1996 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1998 ITypeInfo_Release(other
);
2003 *size
= attr
->cbSizeInstance
;
2005 *align
= attr
->cbAlignment
;
2007 ITypeInfo_ReleaseTypeAttr(other
, attr
);
2008 ITypeInfo_Release(other
);
2013 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
2014 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
2016 ULONG i
, sub
, ptr_size
;
2019 ptr_size
= get_ptr_size(sys
);
2058 *size
= sizeof(DATE
);
2061 *size
= sizeof(VARIANT
);
2063 if(sys
== SYS_WIN32
)
2064 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2068 *size
= sizeof(DECIMAL
);
2075 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2076 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2077 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2082 case VT_USERDEFINED
:
2083 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2085 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2099 /**********************************************************************
2101 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2103 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
2108 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2110 if (where
!= DO_NOT_SEEK
)
2112 where
+= pcx
->oStart
;
2113 if (where
> pcx
->length
)
2116 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2124 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2126 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2127 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2129 MSFT_Seek(pcx
, where
);
2130 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2131 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2136 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2141 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2142 FromLEDWords(buffer
, ret
);
2147 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2152 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2153 FromLEWords(buffer
, ret
);
2158 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2161 MSFT_GuidEntry entry
;
2164 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2166 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2169 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2171 guid
= heap_alloc(sizeof(TLBGuid
));
2173 guid
->offset
= offs
;
2174 guid
->guid
= entry
.guid
;
2175 guid
->hreftype
= entry
.hreftype
;
2177 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2179 offs
+= sizeof(MSFT_GuidEntry
);
2183 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2187 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2188 if(ret
->offset
== offset
){
2189 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2197 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2199 MSFT_NameIntro niName
;
2203 ERR_(typelib
)("bad offset %d\n", offset
);
2207 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2208 pcx
->pTblDir
->pNametab
.offset
+offset
);
2210 return niName
.hreftype
;
2213 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2216 MSFT_NameIntro intro
;
2218 int offs
= 0, lengthInChars
;
2220 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2224 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2227 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2228 intro
.namelen
&= 0xFF;
2229 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2231 len_piece
= (len_piece
+ 4) & ~0x3;
2235 string
= heap_alloc(len_piece
+ 1);
2236 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2237 string
[intro
.namelen
] = '\0';
2239 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2240 string
, -1, NULL
, 0);
2241 if (!lengthInChars
) {
2243 return E_UNEXPECTED
;
2246 tlbstr
= heap_alloc(sizeof(TLBString
));
2248 tlbstr
->offset
= offs
;
2249 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2250 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2254 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2260 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2264 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2265 if (tlbstr
->offset
== offset
) {
2266 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2274 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2278 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2279 if (tlbstr
->offset
== offset
) {
2280 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2289 * read a value and fill a VARIANT structure
2291 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2295 TRACE_(typelib
)("\n");
2297 if(offset
<0) { /* data are packed in here */
2298 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2299 V_I4(pVar
) = offset
& 0x3ffffff;
2302 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2303 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2304 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2305 switch (V_VT(pVar
)){
2306 case VT_EMPTY
: /* FIXME: is this right? */
2307 case VT_NULL
: /* FIXME: is this right? */
2308 case VT_I2
: /* this should not happen */
2319 case VT_VOID
: /* FIXME: is this right? */
2327 case VT_DECIMAL
: /* FIXME: is this right? */
2330 /* pointer types with known behaviour */
2333 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2335 V_BSTR(pVar
) = NULL
;
2337 ptr
= heap_alloc_zero(size
);
2338 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2339 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2340 /* FIXME: do we need a AtoW conversion here? */
2341 V_UNION(pVar
, bstrVal
[size
])='\0';
2342 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2347 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2354 case VT_USERDEFINED
:
2360 case VT_STREAMED_OBJECT
:
2361 case VT_STORED_OBJECT
:
2362 case VT_BLOB_OBJECT
:
2367 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2371 if(size
>0) /* (big|small) endian correct? */
2372 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2376 * create a linked list with custom data
2378 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2384 TRACE_(typelib
)("\n");
2386 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2390 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2391 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2392 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2393 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2394 list_add_head(custdata_list
, &pNew
->entry
);
2395 offset
= entry
.next
;
2400 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2403 pTd
->vt
=type
& VT_TYPEMASK
;
2405 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2407 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2410 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2412 return (invkind
== INVOKE_PROPERTYGET
||
2413 invkind
== INVOKE_PROPERTYPUT
||
2414 invkind
== INVOKE_PROPERTYPUTREF
);
2418 MSFT_DoFuncs(TLBContext
* pcx
,
2423 TLBFuncDesc
** pptfd
)
2426 * member information is stored in a data structure at offset
2427 * indicated by the memoffset field of the typeinfo structure
2428 * There are several distinctive parts.
2429 * The first part starts with a field that holds the total length
2430 * of this (first) part excluding this field. Then follow the records,
2431 * for each member there is one record.
2433 * The first entry is always the length of the record (including this
2435 * The rest of the record depends on the type of the member. If there is
2436 * a field indicating the member type (function, variable, interface, etc)
2437 * I have not found it yet. At this time we depend on the information
2438 * in the type info and the usual order how things are stored.
2440 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2443 * Third is an equal sized array with file offsets to the name entry
2446 * The fourth and last (?) part is an array with offsets to the records
2447 * in the first part of this file segment.
2450 int infolen
, nameoffset
, reclength
, i
;
2451 int recoffset
= offset
+ sizeof(INT
);
2453 char *recbuf
= heap_alloc(0xffff);
2454 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2455 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2457 TRACE_(typelib
)("\n");
2459 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2461 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2463 for ( i
= 0; i
< cFuncs
; i
++ )
2467 /* name, eventually add to a hash table */
2468 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2469 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2471 /* read the function information record */
2472 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2474 reclength
&= 0xffff;
2476 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2478 /* size without argument data */
2479 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2480 if (pFuncRec
->FKCCIC
& 0x1000)
2481 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2483 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2484 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2486 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2487 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2489 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2491 if (pFuncRec
->FKCCIC
& 0x2000 )
2493 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2494 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2495 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2498 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2501 ptfd
->Entry
= (TLBString
*)-1;
2503 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2504 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2506 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2507 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2509 /* fill the FuncDesc Structure */
2510 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2511 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2513 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2514 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2515 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2516 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2517 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2518 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2519 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2521 /* nameoffset is sometimes -1 on the second half of a propget/propput
2522 * pair of functions */
2523 if ((nameoffset
== -1) && (i
> 0) &&
2524 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2525 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2526 ptfd
->Name
= ptfd_prev
->Name
;
2528 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2532 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2534 /* do the parameters/arguments */
2535 if(pFuncRec
->nrargs
)
2538 MSFT_ParameterInfo paraminfo
;
2540 ptfd
->funcdesc
.lprgelemdescParam
=
2541 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2543 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2545 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2546 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2548 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2550 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2556 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2559 if (paraminfo
.oName
!= -1)
2560 ptfd
->pParamDesc
[j
].Name
=
2561 MSFT_ReadName( pcx
, paraminfo
.oName
);
2562 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2565 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2566 (pFuncRec
->FKCCIC
& 0x1000) )
2568 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2570 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2572 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2574 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2575 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2577 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2581 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2584 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2585 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2586 pFuncRec
->FKCCIC
& 0x80 )
2589 pFuncRec
->oArgCustData
[j
],
2590 &ptfd
->pParamDesc
[j
].custdata_list
);
2593 /* SEEK value = jump to offset,
2594 * from there jump to the end of record,
2595 * go back by (j-1) arguments
2597 MSFT_ReadLEDWords( ¶minfo
,
2598 sizeof(MSFT_ParameterInfo
), pcx
,
2599 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2600 * sizeof(MSFT_ParameterInfo
)));
2604 /* scode is not used: archaic win16 stuff FIXME: right? */
2605 ptfd
->funcdesc
.cScodes
= 0 ;
2606 ptfd
->funcdesc
.lprgscode
= NULL
;
2610 recoffset
+= reclength
;
2615 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2616 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2618 int infolen
, nameoffset
, reclength
;
2620 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2625 TRACE_(typelib
)("\n");
2627 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2628 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2629 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2630 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2631 recoffset
+= offset
+sizeof(INT
);
2632 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2633 /* name, eventually add to a hash table */
2634 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2635 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2636 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2637 /* read the variable information record */
2638 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2640 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2643 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2644 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2646 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2647 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2649 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2650 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2652 /* fill the VarDesc Structure */
2653 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2654 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2655 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2656 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2657 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2658 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2659 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2660 if(pVarRec
->VarKind
== VAR_CONST
){
2661 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2662 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2663 pVarRec
->OffsValue
, pcx
);
2665 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2666 recoffset
+= reclength
;
2670 /* process Implemented Interfaces of a com class */
2671 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2675 MSFT_RefRecord refrec
;
2678 TRACE_(typelib
)("\n");
2680 pTI
->impltypes
= TLBImplType_Alloc(count
);
2681 pImpl
= pTI
->impltypes
;
2682 for(i
=0;i
<count
;i
++){
2683 if(offset
<0) break; /* paranoia */
2684 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2685 pImpl
->hRef
= refrec
.reftype
;
2686 pImpl
->implflags
=refrec
.flags
;
2687 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2688 offset
=refrec
.onext
;
2694 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2695 * and some structures, and fix the alignment */
2696 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2698 if(info
->typekind
== TKIND_ALIAS
){
2699 switch(info
->tdescAlias
->vt
){
2707 info
->cbSizeInstance
= sizeof(void*);
2708 info
->cbAlignment
= sizeof(void*);
2711 case VT_USERDEFINED
:
2712 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->cbSizeInstance
, &info
->cbAlignment
);
2715 info
->cbSizeInstance
= sizeof(VARIANT
);
2716 info
->cbAlignment
= 8;
2718 if(info
->cbSizeInstance
< sizeof(void*))
2719 info
->cbAlignment
= info
->cbSizeInstance
;
2721 info
->cbAlignment
= sizeof(void*);
2724 }else if(info
->typekind
== TKIND_INTERFACE
||
2725 info
->typekind
== TKIND_DISPATCH
||
2726 info
->typekind
== TKIND_COCLASS
){
2727 info
->cbSizeInstance
= sizeof(void*);
2728 info
->cbAlignment
= sizeof(void*);
2734 * process a typeinfo record
2736 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2739 ITypeLibImpl
* pLibInfo
)
2741 MSFT_TypeInfoBase tiBase
;
2742 ITypeInfoImpl
*ptiRet
;
2744 TRACE_(typelib
)("count=%u\n", count
);
2746 ptiRet
= ITypeInfoImpl_Constructor();
2747 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2748 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2750 /* this is where we are coming from */
2751 ptiRet
->pTypeLib
= pLibInfo
;
2752 ptiRet
->index
=count
;
2754 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2755 ptiRet
->lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2756 ptiRet
->lpstrSchema
=NULL
; /* reserved */
2757 ptiRet
->cbSizeInstance
=tiBase
.size
;
2758 ptiRet
->typekind
=tiBase
.typekind
& 0xF;
2759 ptiRet
->cFuncs
=LOWORD(tiBase
.cElement
);
2760 ptiRet
->cVars
=HIWORD(tiBase
.cElement
);
2761 ptiRet
->cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2762 ptiRet
->wTypeFlags
=tiBase
.flags
;
2763 ptiRet
->wMajorVerNum
=LOWORD(tiBase
.version
);
2764 ptiRet
->wMinorVerNum
=HIWORD(tiBase
.version
);
2765 ptiRet
->cImplTypes
=tiBase
.cImplTypes
;
2766 ptiRet
->cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2767 if(ptiRet
->typekind
== TKIND_ALIAS
){
2769 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2770 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2771 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2775 /* IDLDESC idldescType; *//* never saw this one != zero */
2777 /* name, eventually add to a hash table */
2778 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2779 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2780 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2782 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2783 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2784 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2786 if (ptiRet
->typekind
== TKIND_MODULE
)
2787 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2789 /* note: InfoType's Help file and HelpStringDll come from the containing
2790 * library. Further HelpString and Docstring appear to be the same thing :(
2793 if(ptiRet
->cFuncs
>0 )
2794 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->cFuncs
,
2796 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2798 if(ptiRet
->cVars
>0 )
2799 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->cFuncs
,
2801 tiBase
.memoffset
, &ptiRet
->vardescs
);
2802 if(ptiRet
->cImplTypes
>0 ) {
2803 switch(ptiRet
->typekind
)
2806 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->cImplTypes
,
2809 case TKIND_DISPATCH
:
2810 /* This is not -1 when the interface is a non-base dual interface or
2811 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2812 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2816 if (tiBase
.datatype1
!= -1)
2818 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2819 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2823 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2824 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2828 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2830 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2831 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2832 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2833 typekind_desc
[ptiRet
->typekind
]);
2834 if (TRACE_ON(typelib
))
2835 dump_TypeInfo(ptiRet
);
2840 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2843 INT16 len_str
, len_piece
;
2844 int offs
= 0, lengthInChars
;
2846 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2850 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2853 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2854 len_piece
= len_str
+ sizeof(INT16
);
2856 len_piece
= (len_piece
+ 4) & ~0x3;
2860 string
= heap_alloc(len_piece
+ 1);
2861 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2862 string
[len_str
] = '\0';
2864 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2865 string
, -1, NULL
, 0);
2866 if (!lengthInChars
) {
2868 return E_UNEXPECTED
;
2871 tlbstr
= heap_alloc(sizeof(TLBString
));
2873 tlbstr
->offset
= offs
;
2874 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2875 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2879 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2885 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2890 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2891 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2892 MSFT_ImpInfo impinfo
;
2895 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2897 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2898 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2900 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2901 if(pImpLib
->offset
==impinfo
.oImpFile
)
2904 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2905 ref
->reference
= offs
;
2906 ref
->pImpTLInfo
= pImpLib
;
2907 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2908 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2909 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2910 ref
->index
= TLB_REF_USE_GUID
;
2912 ref
->index
= impinfo
.oGuid
;
2914 ERR("Cannot find a reference\n");
2915 ref
->reference
= -1;
2916 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2919 offs
+= sizeof(impinfo
);
2925 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2926 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2927 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2930 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2931 static CRITICAL_SECTION cache_section
;
2932 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2934 0, 0, &cache_section
,
2935 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2936 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2938 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2941 typedef struct TLB_PEFile
2943 IUnknown IUnknown_iface
;
2946 HRSRC typelib_resource
;
2947 HGLOBAL typelib_global
;
2948 LPVOID typelib_base
;
2951 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2953 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2956 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2958 if (IsEqualIID(riid
, &IID_IUnknown
))
2961 IUnknown_AddRef(iface
);
2965 return E_NOINTERFACE
;
2968 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2970 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2971 return InterlockedIncrement(&This
->refs
);
2974 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2976 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2977 ULONG refs
= InterlockedDecrement(&This
->refs
);
2980 if (This
->typelib_global
)
2981 FreeResource(This
->typelib_global
);
2983 FreeLibrary(This
->dll
);
2989 static const IUnknownVtbl TLB_PEFile_Vtable
=
2991 TLB_PEFile_QueryInterface
,
2996 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2999 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3001 This
= heap_alloc(sizeof(TLB_PEFile
));
3003 return E_OUTOFMEMORY
;
3005 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
3008 This
->typelib_resource
= NULL
;
3009 This
->typelib_global
= NULL
;
3010 This
->typelib_base
= NULL
;
3012 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
3013 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
3017 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
3018 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
3019 if (This
->typelib_resource
)
3021 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
3022 if (This
->typelib_global
)
3024 This
->typelib_base
= LockResource(This
->typelib_global
);
3026 if (This
->typelib_base
)
3028 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
3029 *ppBase
= This
->typelib_base
;
3030 *ppFile
= &This
->IUnknown_iface
;
3036 TRACE("No TYPELIB resource found\n");
3040 TLB_PEFile_Release(&This
->IUnknown_iface
);
3044 typedef struct TLB_NEFile
3046 IUnknown IUnknown_iface
;
3048 LPVOID typelib_base
;
3051 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
3053 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
3056 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3058 if (IsEqualIID(riid
, &IID_IUnknown
))
3061 IUnknown_AddRef(iface
);
3065 return E_NOINTERFACE
;
3068 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
3070 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3071 return InterlockedIncrement(&This
->refs
);
3074 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
3076 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3077 ULONG refs
= InterlockedDecrement(&This
->refs
);
3080 heap_free(This
->typelib_base
);
3086 static const IUnknownVtbl TLB_NEFile_Vtable
=
3088 TLB_NEFile_QueryInterface
,
3093 /***********************************************************************
3094 * read_xx_header [internal]
3096 static int read_xx_header( HFILE lzfd
)
3098 IMAGE_DOS_HEADER mzh
;
3101 LZSeek( lzfd
, 0, SEEK_SET
);
3102 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3104 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3107 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3108 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3111 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3113 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3114 return IMAGE_OS2_SIGNATURE
;
3115 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3116 return IMAGE_NT_SIGNATURE
;
3119 WARN("Can't handle %s files.\n", magic
);
3124 /***********************************************************************
3125 * find_ne_resource [internal]
3127 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3128 DWORD
*resLen
, DWORD
*resOff
)
3130 IMAGE_OS2_HEADER nehd
;
3131 NE_TYPEINFO
*typeInfo
;
3132 NE_NAMEINFO
*nameInfo
;
3138 /* Read in NE header */
3139 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3140 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
3142 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3145 TRACE("No resources in NE dll\n" );
3149 /* Read in resource table */
3150 resTab
= heap_alloc( resTabSize
);
3151 if ( !resTab
) return FALSE
;
3153 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3154 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3156 heap_free( resTab
);
3161 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3163 if (!IS_INTRESOURCE(typeid)) /* named type */
3165 BYTE len
= strlen( typeid );
3166 while (typeInfo
->type_id
)
3168 if (!(typeInfo
->type_id
& 0x8000))
3170 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3171 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
3173 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3174 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3177 else /* numeric type id */
3179 WORD id
= LOWORD(typeid) | 0x8000;
3180 while (typeInfo
->type_id
)
3182 if (typeInfo
->type_id
== id
) goto found_type
;
3183 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3184 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3187 TRACE("No typeid entry found for %p\n", typeid );
3188 heap_free( resTab
);
3192 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3194 if (!IS_INTRESOURCE(resid
)) /* named resource */
3196 BYTE len
= strlen( resid
);
3197 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3199 BYTE
*p
= resTab
+ nameInfo
->id
;
3200 if (nameInfo
->id
& 0x8000) continue;
3201 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3204 else /* numeric resource id */
3206 WORD id
= LOWORD(resid
) | 0x8000;
3207 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3208 if (nameInfo
->id
== id
) goto found_name
;
3210 TRACE("No resid entry found for %p\n", typeid );
3211 heap_free( resTab
);
3215 /* Return resource data */
3216 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3217 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3219 heap_free( resTab
);
3223 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3227 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3230 This
= heap_alloc(sizeof(TLB_NEFile
));
3231 if (!This
) return E_OUTOFMEMORY
;
3233 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3235 This
->typelib_base
= NULL
;
3237 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3238 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3240 DWORD reslen
, offset
;
3241 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3243 This
->typelib_base
= heap_alloc(reslen
);
3244 if( !This
->typelib_base
)
3248 LZSeek( lzfd
, offset
, SEEK_SET
);
3249 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3251 *ppBase
= This
->typelib_base
;
3252 *pdwTLBLength
= reslen
;
3253 *ppFile
= &This
->IUnknown_iface
;
3259 if( lzfd
>= 0) LZClose( lzfd
);
3260 TLB_NEFile_Release(&This
->IUnknown_iface
);
3264 typedef struct TLB_Mapping
3266 IUnknown IUnknown_iface
;
3270 LPVOID typelib_base
;
3273 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3275 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3278 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3280 if (IsEqualIID(riid
, &IID_IUnknown
))
3283 IUnknown_AddRef(iface
);
3287 return E_NOINTERFACE
;
3290 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3292 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3293 return InterlockedIncrement(&This
->refs
);
3296 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3298 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3299 ULONG refs
= InterlockedDecrement(&This
->refs
);
3302 if (This
->typelib_base
)
3303 UnmapViewOfFile(This
->typelib_base
);
3305 CloseHandle(This
->mapping
);
3306 if (This
->file
!= INVALID_HANDLE_VALUE
)
3307 CloseHandle(This
->file
);
3313 static const IUnknownVtbl TLB_Mapping_Vtable
=
3315 TLB_Mapping_QueryInterface
,
3320 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3324 This
= heap_alloc(sizeof(TLB_Mapping
));
3326 return E_OUTOFMEMORY
;
3328 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3330 This
->file
= INVALID_HANDLE_VALUE
;
3331 This
->mapping
= NULL
;
3332 This
->typelib_base
= NULL
;
3334 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3335 if (INVALID_HANDLE_VALUE
!= This
->file
)
3337 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3340 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3341 if(This
->typelib_base
)
3343 /* retrieve file size */
3344 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3345 *ppBase
= This
->typelib_base
;
3346 *ppFile
= &This
->IUnknown_iface
;
3352 IUnknown_Release(&This
->IUnknown_iface
);
3353 return TYPE_E_CANTLOADLIBRARY
;
3356 /****************************************************************************
3359 * find the type of the typelib file and map the typelib resource into
3363 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3364 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3366 ITypeLibImpl
*entry
;
3369 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3370 LPVOID pBase
= NULL
;
3371 DWORD dwTLBLength
= 0;
3372 IUnknown
*pFile
= NULL
;
3377 index_str
= strrchrW(pszFileName
, '\\');
3378 if(index_str
&& *++index_str
!= '\0')
3381 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3382 if(*end_ptr
== '\0')
3384 int str_len
= index_str
- pszFileName
- 1;
3386 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3387 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3392 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3394 if(strchrW(file
, '\\'))
3396 lstrcpyW(pszPath
, file
);
3400 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3401 pszPath
[len
] = '\\';
3402 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3406 if(file
!= pszFileName
) heap_free(file
);
3408 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_ALWAYS
,
3409 FILE_ATTRIBUTE_NORMAL
, NULL
);
3410 if(h
!= INVALID_HANDLE_VALUE
){
3411 FILE_NAME_INFORMATION
*info
;
3412 char data
[MAX_PATH
* sizeof(WCHAR
) + sizeof(info
->FileNameLength
)];
3415 info
= (FILE_NAME_INFORMATION
*)data
;
3416 /* GetFileInformationByHandleEx returns the path of the file without
3417 * WOW64 redirection */
3418 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, data
, sizeof(data
));
3420 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3421 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3426 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3428 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3429 EnterCriticalSection(&cache_section
);
3430 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3432 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3434 TRACE("cache hit\n");
3435 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3436 ITypeLib2_AddRef(*ppTypeLib
);
3437 LeaveCriticalSection(&cache_section
);
3441 LeaveCriticalSection(&cache_section
);
3443 /* now actually load and parse the typelib */
3445 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3446 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3447 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3448 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3449 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3452 if (dwTLBLength
>= 4)
3454 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3455 if (dwSignature
== MSFT_SIGNATURE
)
3456 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3457 else if (dwSignature
== SLTG_SIGNATURE
)
3458 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3461 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3462 ret
= TYPE_E_CANTLOADLIBRARY
;
3466 ret
= TYPE_E_CANTLOADLIBRARY
;
3467 IUnknown_Release(pFile
);
3471 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3473 TRACE("adding to cache\n");
3474 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3475 lstrcpyW(impl
->path
, pszPath
);
3476 /* We should really canonicalise the path here. */
3477 impl
->index
= index
;
3479 /* FIXME: check if it has added already in the meantime */
3480 EnterCriticalSection(&cache_section
);
3481 list_add_head(&tlb_cache
, &impl
->entry
);
3482 LeaveCriticalSection(&cache_section
);
3488 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3490 ret
= TYPE_E_CANTLOADLIBRARY
;
3497 /*================== ITypeLib(2) Methods ===================================*/
3499 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3501 ITypeLibImpl
* pTypeLibImpl
;
3503 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3504 if (!pTypeLibImpl
) return NULL
;
3506 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3507 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3508 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3509 pTypeLibImpl
->ref
= 1;
3511 list_init(&pTypeLibImpl
->implib_list
);
3512 list_init(&pTypeLibImpl
->custdata_list
);
3513 list_init(&pTypeLibImpl
->name_list
);
3514 list_init(&pTypeLibImpl
->string_list
);
3515 list_init(&pTypeLibImpl
->guid_list
);
3516 list_init(&pTypeLibImpl
->ref_list
);
3517 pTypeLibImpl
->dispatch_href
= -1;
3519 return pTypeLibImpl
;
3522 /****************************************************************************
3523 * ITypeLib2_Constructor_MSFT
3525 * loading an MSFT typelib from an in-memory image
3527 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3531 MSFT_Header tlbHeader
;
3532 MSFT_SegDir tlbSegDir
;
3533 ITypeLibImpl
* pTypeLibImpl
;
3536 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3538 pTypeLibImpl
= TypeLibImpl_Constructor();
3539 if (!pTypeLibImpl
) return NULL
;
3541 /* get pointer to beginning of typelib data */
3545 cx
.pLibInfo
= pTypeLibImpl
;
3546 cx
.length
= dwTLBLength
;
3549 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3550 TRACE_(typelib
)("header:\n");
3551 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3552 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3553 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3556 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3558 /* there is a small amount of information here until the next important
3560 * the segment directory . Try to calculate the amount of data */
3561 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3563 /* now read the segment directory */
3564 TRACE("read segment directory (at %d)\n",lPSegDir
);
3565 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3566 cx
.pTblDir
= &tlbSegDir
;
3568 /* just check two entries */
3569 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3571 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3572 heap_free(pTypeLibImpl
);
3576 MSFT_ReadAllNames(&cx
);
3577 MSFT_ReadAllStrings(&cx
);
3578 MSFT_ReadAllGuids(&cx
);
3580 /* now fill our internal data */
3581 /* TLIBATTR fields */
3582 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3584 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3585 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3586 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3587 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3588 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3590 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3591 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3593 /* name, eventually add to a hash table */
3594 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3597 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3598 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3600 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3603 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3604 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3607 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3610 if(tlbHeader
.CustomDataOffset
>= 0)
3612 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3615 /* fill in type descriptions */
3616 if(tlbSegDir
.pTypdescTab
.length
> 0)
3618 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3620 pTypeLibImpl
->ctTypeDesc
= cTD
;
3621 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3622 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3625 /* FIXME: add several sanity checks here */
3626 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3627 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3629 /* FIXME: check safearray */
3631 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3633 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3635 else if(td
[0] == VT_CARRAY
)
3637 /* array descr table here */
3638 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3640 else if(td
[0] == VT_USERDEFINED
)
3642 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3644 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3647 /* second time around to fill the array subscript info */
3650 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3651 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3653 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3654 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3657 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3659 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3661 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3663 for(j
= 0; j
<td
[2]; j
++)
3665 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3666 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3667 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3668 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3673 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3674 ERR("didn't find array description data\n");
3679 /* imported type libs */
3680 if(tlbSegDir
.pImpFiles
.offset
>0)
3683 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3686 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3690 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3691 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3692 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3694 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3695 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3696 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3697 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3700 name
= heap_alloc_zero(size
+1);
3701 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3702 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3705 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3706 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3708 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3712 MSFT_ReadAllRefs(&cx
);
3714 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3717 if(tlbHeader
.nrtypeinfos
>= 0 )
3719 ITypeInfoImpl
**ppTI
;
3721 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3723 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3725 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3728 (pTypeLibImpl
->TypeInfoCount
)++;
3733 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3734 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3735 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3739 TRACE("(%p)\n", pTypeLibImpl
);
3740 return &pTypeLibImpl
->ITypeLib2_iface
;
3744 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3750 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3751 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3755 guid
->Data4
[0] = s
>> 8;
3756 guid
->Data4
[1] = s
& 0xff;
3759 for(i
= 0; i
< 6; i
++) {
3760 memcpy(b
, str
+ 24 + 2 * i
, 2);
3761 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3766 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3773 bytelen
= *(const WORD
*)ptr
;
3774 if(bytelen
== 0xffff) return 2;
3776 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3777 tmp_str
= SysAllocStringLen(NULL
, len
);
3779 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3780 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3781 SysFreeString(tmp_str
);
3786 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3791 bytelen
= *(const WORD
*)ptr
;
3792 if(bytelen
== 0xffff) return 2;
3793 *str
= heap_alloc(bytelen
+ 1);
3794 memcpy(*str
, ptr
+ 2, bytelen
);
3795 (*str
)[bytelen
] = '\0';
3799 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3804 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3805 if (tlbstr
->offset
== offset
)
3809 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3810 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3811 SysFreeString(tmp_str
);
3816 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3818 char *ptr
= pLibBlk
;
3821 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3822 FIXME("libblk magic = %04x\n", w
);
3827 if((w
= *(WORD
*)ptr
) != 0xffff) {
3828 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3833 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3835 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3837 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3840 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3841 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3844 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3845 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3847 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3850 ptr
+= 4; /* skip res12 */
3852 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3855 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3858 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3861 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3862 ptr
+= sizeof(GUID
);
3864 return ptr
- (char*)pLibBlk
;
3867 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3872 } sltg_ref_lookup_t
;
3874 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3875 HREFTYPE
*typelib_ref
)
3877 if(table
&& typeinfo_ref
< table
->num
)
3879 *typelib_ref
= table
->refs
[typeinfo_ref
];
3883 ERR_(typelib
)("Unable to find reference\n");
3888 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3893 if((*pType
& 0xe00) == 0xe00) {
3895 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3896 pTD
= pTD
->u
.lptdesc
;
3898 switch(*pType
& 0x3f) {
3901 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3902 pTD
= pTD
->u
.lptdesc
;
3905 case VT_USERDEFINED
:
3906 pTD
->vt
= VT_USERDEFINED
;
3907 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3913 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3916 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3918 pTD
->vt
= VT_CARRAY
;
3919 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3920 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3921 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3922 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3924 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3930 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3934 pTD
->vt
= VT_SAFEARRAY
;
3935 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3936 pTD
= pTD
->u
.lptdesc
;
3940 pTD
->vt
= *pType
& 0x3f;
3949 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3950 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3952 /* Handle [in/out] first */
3953 if((*pType
& 0xc000) == 0xc000)
3954 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3955 else if(*pType
& 0x8000)
3956 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3957 else if(*pType
& 0x4000)
3958 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3960 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3963 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3966 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3968 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3972 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3977 TLBRefType
*ref_type
;
3978 sltg_ref_lookup_t
*table
;
3979 HREFTYPE typelib_ref
;
3981 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3982 FIXME("Ref magic = %x\n", pRef
->magic
);
3985 name
= ( (char*)pRef
->names
+ pRef
->number
);
3987 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3988 table
->num
= pRef
->number
>> 3;
3990 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3992 /* We don't want the first href to be 0 */
3993 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3995 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3997 unsigned int lib_offs
, type_num
;
3999 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
4001 name
+= SLTG_ReadStringA(name
, &refname
);
4002 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
4003 FIXME_(typelib
)("Can't sscanf ref\n");
4004 if(lib_offs
!= 0xffff) {
4007 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
4008 if(import
->offset
== lib_offs
)
4011 if(&import
->entry
== &pTL
->implib_list
) {
4012 char fname
[MAX_PATH
+1];
4016 import
= heap_alloc_zero(sizeof(*import
));
4017 import
->offset
= lib_offs
;
4018 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
4019 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
4020 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
4021 &import
->wVersionMajor
,
4022 &import
->wVersionMinor
,
4023 &import
->lcid
, fname
) != 4) {
4024 FIXME_(typelib
)("can't sscanf ref %s\n",
4025 pNameTable
+ lib_offs
+ 40);
4027 len
= strlen(fname
);
4028 if(fname
[len
-1] != '#')
4029 FIXME("fname = %s\n", fname
);
4030 fname
[len
-1] = '\0';
4031 import
->name
= TLB_MultiByteToBSTR(fname
);
4032 list_add_tail(&pTL
->implib_list
, &import
->entry
);
4034 ref_type
->pImpTLInfo
= import
;
4036 /* Store a reference to IDispatch */
4037 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
4038 pTL
->dispatch_href
= typelib_ref
;
4040 } else { /* internal ref */
4041 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
4043 ref_type
->reference
= typelib_ref
;
4044 ref_type
->index
= type_num
;
4047 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
4049 table
->refs
[ref
] = typelib_ref
;
4052 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
4053 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
4054 dump_TLBRefType(pTL
);
4058 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
4059 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
4061 SLTG_ImplInfo
*info
;
4062 TLBImplType
*pImplType
;
4063 /* I don't really get this structure, usually it's 0x16 bytes
4064 long, but iuser.tlb contains some that are 0x18 bytes long.
4065 That's ok because we can use the next ptr to jump to the next
4066 one. But how do we know the length of the last one? The WORD
4067 at offs 0x8 might be the clue. For now I'm just assuming that
4068 the last one is the regular 0x16 bytes. */
4070 info
= (SLTG_ImplInfo
*)pBlk
;
4073 if(info
->next
== 0xffff)
4075 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4078 info
= (SLTG_ImplInfo
*)pBlk
;
4079 pTI
->impltypes
= TLBImplType_Alloc(pTI
->cImplTypes
);
4080 pImplType
= pTI
->impltypes
;
4082 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4083 pImplType
->implflags
= info
->impltypeflags
;
4086 if(info
->next
== 0xffff)
4089 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4090 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4092 info
++; /* see comment at top of function */
4096 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4097 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4099 TLBVarDesc
*pVarDesc
;
4100 const TLBString
*prevName
= NULL
;
4101 SLTG_Variable
*pItem
;
4105 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4107 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4108 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4110 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4112 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4113 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4114 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4118 if (pItem
->name
== 0xfffe)
4119 pVarDesc
->Name
= prevName
;
4121 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4123 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4124 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4125 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4127 if(pItem
->flags
& 0x02)
4128 pType
= &pItem
->type
;
4130 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4132 if (pItem
->flags
& ~0xda)
4133 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4135 SLTG_DoElem(pType
, pBlk
,
4136 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4138 if (TRACE_ON(typelib
)) {
4140 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4141 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4144 if (pItem
->flags
& 0x40) {
4145 TRACE_(typelib
)("VAR_DISPATCH\n");
4146 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4148 else if (pItem
->flags
& 0x10) {
4149 TRACE_(typelib
)("VAR_CONST\n");
4150 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4151 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4152 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4153 if (pItem
->flags
& 0x08)
4154 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4156 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4162 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4164 TRACE_(typelib
)("len = %u\n", len
);
4165 if (len
== 0xffff) {
4168 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4169 str
= SysAllocStringLen(NULL
, alloc_len
);
4170 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4172 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4173 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4182 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4183 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4186 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4191 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4192 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4193 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4196 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4197 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4199 if (pItem
->flags
& 0x80)
4200 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4202 prevName
= pVarDesc
->Name
;
4207 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4208 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4210 SLTG_Function
*pFunc
;
4212 TLBFuncDesc
*pFuncDesc
;
4214 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4216 pFuncDesc
= pTI
->funcdescs
;
4217 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4218 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4223 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4224 case SLTG_FUNCTION_MAGIC
:
4225 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4227 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4228 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4230 case SLTG_STATIC_FUNCTION_MAGIC
:
4231 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4234 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4237 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4239 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4240 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4241 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4242 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4243 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4244 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4246 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4247 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4249 if(pFunc
->retnextopt
& 0x80)
4250 pType
= &pFunc
->rettype
;
4252 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4254 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4256 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4257 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4258 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4260 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4262 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4263 char *paramName
= pNameTable
+ *pArg
;
4265 /* If arg type follows then paramName points to the 2nd
4266 letter of the name, else the next WORD is an offset to
4267 the arg type and paramName points to the first letter.
4268 So let's take one char off paramName and see if we're
4269 pointing at an alpha-numeric char. However if *pArg is
4270 0xffff or 0xfffe then the param has no name, the former
4271 meaning that the next WORD is the type, the latter
4272 meaning that the next WORD is an offset to the type. */
4277 else if(*pArg
== 0xfffe) {
4281 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4286 if(HaveOffs
) { /* the next word is an offset to type */
4287 pType
= (WORD
*)(pBlk
+ *pArg
);
4288 SLTG_DoElem(pType
, pBlk
,
4289 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4294 pArg
= SLTG_DoElem(pArg
, pBlk
,
4295 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4298 /* Are we an optional param ? */
4299 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4300 pFuncDesc
->funcdesc
.cParamsOpt
)
4301 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4304 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4305 paramName
- pNameTable
, pTI
->pTypeLib
);
4307 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4311 pTI
->cFuncs
= cFuncs
;
4314 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4315 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4316 SLTG_TypeInfoTail
*pTITail
)
4319 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4321 if(pTIHeader
->href_table
!= 0xffffffff) {
4322 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4328 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4329 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4331 heap_free(ref_lookup
);
4335 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4336 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4337 const SLTG_TypeInfoTail
*pTITail
)
4340 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4342 if(pTIHeader
->href_table
!= 0xffffffff) {
4343 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4349 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4350 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4353 if (pTITail
->funcs_off
!= 0xffff)
4354 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4356 heap_free(ref_lookup
);
4358 if (TRACE_ON(typelib
))
4359 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4362 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4363 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4364 const SLTG_TypeInfoTail
*pTITail
)
4366 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4369 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4370 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4371 const SLTG_TypeInfoTail
*pTITail
)
4374 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4376 if (pTITail
->simple_alias
) {
4377 /* if simple alias, no more processing required */
4378 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4379 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4383 if(pTIHeader
->href_table
!= 0xffffffff) {
4384 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4388 /* otherwise it is an offset to a type */
4389 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4391 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4392 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4394 heap_free(ref_lookup
);
4397 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4398 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4399 const SLTG_TypeInfoTail
*pTITail
)
4401 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4402 if (pTIHeader
->href_table
!= 0xffffffff)
4403 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4406 if (pTITail
->vars_off
!= 0xffff)
4407 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4409 if (pTITail
->funcs_off
!= 0xffff)
4410 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4412 if (pTITail
->impls_off
!= 0xffff)
4413 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4415 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4416 * of dispinterface functions including the IDispatch ones, so
4417 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4418 pTI
->cbSizeVft
= pTI
->cFuncs
* pTI
->pTypeLib
->ptr_size
;
4420 heap_free(ref_lookup
);
4421 if (TRACE_ON(typelib
))
4422 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4425 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4426 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4427 const SLTG_TypeInfoTail
*pTITail
)
4429 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4432 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4433 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4434 const SLTG_TypeInfoTail
*pTITail
)
4436 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4437 if (pTIHeader
->href_table
!= 0xffffffff)
4438 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4441 if (pTITail
->vars_off
!= 0xffff)
4442 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4444 if (pTITail
->funcs_off
!= 0xffff)
4445 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4446 heap_free(ref_lookup
);
4447 if (TRACE_ON(typelib
))
4451 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4452 manageable copy of it into this */
4465 } SLTG_InternalOtherTypeInfo
;
4467 /****************************************************************************
4468 * ITypeLib2_Constructor_SLTG
4470 * loading a SLTG typelib from an in-memory image
4472 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4474 ITypeLibImpl
*pTypeLibImpl
;
4475 SLTG_Header
*pHeader
;
4476 SLTG_BlkEntry
*pBlkEntry
;
4480 LPVOID pBlk
, pFirstBlk
;
4481 SLTG_LibBlk
*pLibBlk
;
4482 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4483 char *pAfterOTIBlks
= NULL
;
4484 char *pNameTable
, *ptr
;
4487 ITypeInfoImpl
**ppTypeInfoImpl
;
4489 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4492 pTypeLibImpl
= TypeLibImpl_Constructor();
4493 if (!pTypeLibImpl
) return NULL
;
4497 TRACE_(typelib
)("header:\n");
4498 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4499 pHeader
->nrOfFileBlks
);
4500 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4501 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4502 pHeader
->SLTG_magic
);
4506 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4507 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4509 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4510 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4512 /* Next we have a magic block */
4513 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4515 /* Let's see if we're still in sync */
4516 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4517 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4518 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4521 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4522 sizeof(SLTG_DIR_MAGIC
))) {
4523 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4527 pIndex
= (SLTG_Index
*)(pMagic
+1);
4529 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4531 pFirstBlk
= pPad9
+ 1;
4533 /* We'll set up a ptr to the main library block, which is the last one. */
4535 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4536 pBlkEntry
[order
].next
!= 0;
4537 order
= pBlkEntry
[order
].next
- 1, i
++) {
4538 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4542 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4544 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4549 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4551 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4554 ptr
= (char*)pLibBlk
+ len
;
4556 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4560 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4562 w
= *(WORD
*)(ptr
+ 2);
4565 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4566 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4567 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4569 w
= *(WORD
*)(ptr
+ 4 + len
);
4571 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4573 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4574 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4575 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4577 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4578 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4579 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4581 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4582 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4585 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4586 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4587 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4588 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4589 len
+= sizeof(SLTG_OtherTypeInfo
);
4593 pAfterOTIBlks
= ptr
;
4595 /* Skip this WORD and get the next DWORD */
4596 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4598 /* Now add this to pLibBLk look at what we're pointing at and
4599 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4600 dust and we should be pointing at the beginning of the name
4603 pNameTable
= (char*)pLibBlk
+ len
;
4605 switch(*(WORD
*)pNameTable
) {
4612 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4616 pNameTable
+= 0x216;
4620 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4622 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4625 /* Hopefully we now have enough ptrs set up to actually read in
4626 some TypeInfos. It's not clear which order to do them in, so
4627 I'll just follow the links along the BlkEntry chain and read
4628 them in the order in which they are in the file */
4630 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4631 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4633 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4634 pBlkEntry
[order
].next
!= 0;
4635 order
= pBlkEntry
[order
].next
- 1, i
++) {
4637 SLTG_TypeInfoHeader
*pTIHeader
;
4638 SLTG_TypeInfoTail
*pTITail
;
4639 SLTG_MemberHeader
*pMemHeader
;
4641 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4642 FIXME_(typelib
)("Index strings don't match\n");
4643 heap_free(pOtherTypeInfoBlks
);
4648 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4649 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4650 heap_free(pOtherTypeInfoBlks
);
4653 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4654 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4655 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4657 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4658 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4659 (*ppTypeInfoImpl
)->index
= i
;
4660 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4661 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4662 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4663 (*ppTypeInfoImpl
)->typekind
= pTIHeader
->typekind
;
4664 (*ppTypeInfoImpl
)->wMajorVerNum
= pTIHeader
->major_version
;
4665 (*ppTypeInfoImpl
)->wMinorVerNum
= pTIHeader
->minor_version
;
4666 (*ppTypeInfoImpl
)->wTypeFlags
=
4667 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4669 if((*ppTypeInfoImpl
)->wTypeFlags
& TYPEFLAG_FDUAL
)
4670 (*ppTypeInfoImpl
)->typekind
= TKIND_DISPATCH
;
4672 if((pTIHeader
->typeflags1
& 7) != 2)
4673 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4674 if(pTIHeader
->typeflags3
!= 2)
4675 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4677 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4678 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4679 typekind_desc
[pTIHeader
->typekind
],
4680 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4681 (*ppTypeInfoImpl
)->wTypeFlags
);
4683 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4685 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4687 (*ppTypeInfoImpl
)->cbAlignment
= pTITail
->cbAlignment
;
4688 (*ppTypeInfoImpl
)->cbSizeInstance
= pTITail
->cbSizeInstance
;
4689 (*ppTypeInfoImpl
)->cbSizeVft
= pTITail
->cbSizeVft
;
4691 switch(pTIHeader
->typekind
) {
4693 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4694 pTIHeader
, pTITail
);
4698 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4699 pTIHeader
, pTITail
);
4702 case TKIND_INTERFACE
:
4703 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4704 pTIHeader
, pTITail
);
4708 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4709 pTIHeader
, pTITail
);
4713 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4714 pTIHeader
, pTITail
);
4717 case TKIND_DISPATCH
:
4718 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4719 pTIHeader
, pTITail
);
4723 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4724 pTIHeader
, pTITail
);
4728 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4733 /* could get cFuncs, cVars and cImplTypes from here
4734 but we've already set those */
4735 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4751 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4754 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4755 FIXME("Somehow processed %d TypeInfos\n", i
);
4756 heap_free(pOtherTypeInfoBlks
);
4760 heap_free(pOtherTypeInfoBlks
);
4761 return &pTypeLibImpl
->ITypeLib2_iface
;
4764 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4766 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4768 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4770 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4771 IsEqualIID(riid
,&IID_ITypeLib
)||
4772 IsEqualIID(riid
,&IID_ITypeLib2
))
4774 *ppv
= &This
->ITypeLib2_iface
;
4776 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4777 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4779 *ppv
= &This
->ICreateTypeLib2_iface
;
4784 TRACE("-- Interface: E_NOINTERFACE\n");
4785 return E_NOINTERFACE
;
4788 IUnknown_AddRef((IUnknown
*)*ppv
);
4792 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4794 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4795 ULONG ref
= InterlockedIncrement(&This
->ref
);
4797 TRACE("(%p) ref=%u\n", This
, ref
);
4802 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4804 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4805 ULONG ref
= InterlockedDecrement(&This
->ref
);
4807 TRACE("(%p) ref=%u\n",This
, ref
);
4811 TLBImpLib
*pImpLib
, *pImpLibNext
;
4812 TLBRefType
*ref_type
;
4813 TLBString
*tlbstr
, *tlbstr_next
;
4814 TLBGuid
*tlbguid
, *tlbguid_next
;
4818 /* remove cache entry */
4821 TRACE("removing from cache list\n");
4822 EnterCriticalSection(&cache_section
);
4823 if(This
->entry
.next
)
4824 list_remove(&This
->entry
);
4825 LeaveCriticalSection(&cache_section
);
4826 heap_free(This
->path
);
4828 TRACE(" destroying ITypeLib(%p)\n",This
);
4830 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4831 list_remove(&tlbstr
->entry
);
4832 SysFreeString(tlbstr
->str
);
4836 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4837 list_remove(&tlbstr
->entry
);
4838 SysFreeString(tlbstr
->str
);
4842 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4843 list_remove(&tlbguid
->entry
);
4847 TLB_FreeCustData(&This
->custdata_list
);
4849 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4850 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4851 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4853 heap_free(This
->pTypeDesc
);
4855 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4857 if (pImpLib
->pImpTypeLib
)
4858 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4859 SysFreeString(pImpLib
->name
);
4861 list_remove(&pImpLib
->entry
);
4865 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4867 list_remove(&ref_type
->entry
);
4868 heap_free(ref_type
);
4871 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4872 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4873 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4875 heap_free(This
->typeinfos
);
4883 /* ITypeLib::GetTypeInfoCount
4885 * Returns the number of type descriptions in the type library
4887 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4889 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4890 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4891 return This
->TypeInfoCount
;
4894 /* ITypeLib::GetTypeInfo
4896 * retrieves the specified type description in the library.
4898 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4901 ITypeInfo
**ppTInfo
)
4903 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4905 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4908 return E_INVALIDARG
;
4910 if(index
>= This
->TypeInfoCount
)
4911 return TYPE_E_ELEMENTNOTFOUND
;
4913 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4914 ITypeInfo_AddRef(*ppTInfo
);
4920 /* ITypeLibs::GetTypeInfoType
4922 * Retrieves the type of a type description.
4924 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4929 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4931 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4934 return E_INVALIDARG
;
4936 if(index
>= This
->TypeInfoCount
)
4937 return TYPE_E_ELEMENTNOTFOUND
;
4939 *pTKind
= This
->typeinfos
[index
]->typekind
;
4944 /* ITypeLib::GetTypeInfoOfGuid
4946 * Retrieves the type description that corresponds to the specified GUID.
4949 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4952 ITypeInfo
**ppTInfo
)
4954 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4957 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4959 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4960 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4961 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4962 ITypeInfo_AddRef(*ppTInfo
);
4967 return TYPE_E_ELEMENTNOTFOUND
;
4970 /* ITypeLib::GetLibAttr
4972 * Retrieves the structure that contains the library's attributes.
4975 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4979 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4981 TRACE("(%p, %p)\n", This
, attr
);
4983 if (!attr
) return E_INVALIDARG
;
4985 *attr
= heap_alloc(sizeof(**attr
));
4986 if (!*attr
) return E_OUTOFMEMORY
;
4988 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4989 (*attr
)->lcid
= This
->set_lcid
;
4990 (*attr
)->syskind
= This
->syskind
;
4991 (*attr
)->wMajorVerNum
= This
->ver_major
;
4992 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4993 (*attr
)->wLibFlags
= This
->libflags
;
4998 /* ITypeLib::GetTypeComp
5000 * Enables a client compiler to bind to a library's types, variables,
5001 * constants, and global functions.
5004 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
5006 ITypeComp
**ppTComp
)
5008 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5010 TRACE("(%p)->(%p)\n",This
,ppTComp
);
5011 *ppTComp
= &This
->ITypeComp_iface
;
5012 ITypeComp_AddRef(*ppTComp
);
5017 /* ITypeLib::GetDocumentation
5019 * Retrieves the library's documentation string, the complete Help file name
5020 * and path, and the context identifier for the library Help topic in the Help
5023 * On a successful return all non-null BSTR pointers will have been set,
5026 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
5030 BSTR
*pBstrDocString
,
5031 DWORD
*pdwHelpContext
,
5032 BSTR
*pBstrHelpFile
)
5034 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5035 HRESULT result
= E_INVALIDARG
;
5038 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
5040 pBstrName
, pBstrDocString
,
5041 pdwHelpContext
, pBstrHelpFile
);
5045 /* documentation for the typelib */
5050 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
5058 if (This
->DocString
)
5060 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
5064 *pBstrDocString
= NULL
;
5068 *pdwHelpContext
= This
->dwHelpContext
;
5074 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5078 *pBstrHelpFile
= NULL
;
5085 /* for a typeinfo */
5086 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5088 if(SUCCEEDED(result
))
5090 result
= ITypeInfo_GetDocumentation(pTInfo
,
5094 pdwHelpContext
, pBstrHelpFile
);
5096 ITypeInfo_Release(pTInfo
);
5101 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5103 if (pBstrName
) SysFreeString (*pBstrName
);
5105 return STG_E_INSUFFICIENTMEMORY
;
5110 * Indicates whether a passed-in string contains the name of a type or member
5111 * described in the library.
5114 static HRESULT WINAPI
ITypeLib2_fnIsName(
5120 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5122 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5124 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5128 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5129 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5130 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5131 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5132 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5134 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5135 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5136 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5137 goto ITypeLib2_fnIsName_exit
;
5140 for(vrc
= 0; vrc
< pTInfo
->cVars
; ++vrc
){
5141 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5142 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5148 ITypeLib2_fnIsName_exit
:
5149 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5150 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5155 /* ITypeLib::FindName
5157 * Finds occurrences of a type description in a type library. This may be used
5158 * to quickly verify that a name exists in a type library.
5161 static HRESULT WINAPI
ITypeLib2_fnFindName(
5165 ITypeInfo
**ppTInfo
,
5169 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5174 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5176 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5177 return E_INVALIDARG
;
5179 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5180 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
) {
5181 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5185 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
5186 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5187 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5190 if(!TLB_str_memcmp(name
, func
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
5191 for(pc
= 0; pc
< func
->funcdesc
.cParams
; pc
++) {
5192 if(!TLB_str_memcmp(name
, func
->pParamDesc
[pc
].Name
, len
))
5193 goto ITypeLib2_fnFindName_exit
;
5197 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->cVars
, name
);
5199 goto ITypeLib2_fnFindName_exit
;
5202 ITypeLib2_fnFindName_exit
:
5203 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5204 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5207 TRACE("found %d typeinfos\n", count
);
5214 /* ITypeLib::ReleaseTLibAttr
5216 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5219 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5221 TLIBATTR
*pTLibAttr
)
5223 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5224 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5225 heap_free(pTLibAttr
);
5228 /* ITypeLib2::GetCustData
5230 * gets the custom data
5232 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5237 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5238 TLBCustData
*pCData
;
5240 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5242 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5244 return TYPE_E_ELEMENTNOTFOUND
;
5246 VariantInit(pVarVal
);
5247 VariantCopy(pVarVal
, &pCData
->data
);
5252 /* ITypeLib2::GetLibStatistics
5254 * Returns statistics about a type library that are required for efficient
5255 * sizing of hash tables.
5258 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5260 ULONG
*pcUniqueNames
,
5261 ULONG
*pcchUniqueNames
)
5263 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5265 FIXME("(%p): stub!\n", This
);
5267 if(pcUniqueNames
) *pcUniqueNames
=1;
5268 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5272 /* ITypeLib2::GetDocumentation2
5274 * Retrieves the library's documentation string, the complete Help file name
5275 * and path, the localization context to use, and the context ID for the
5276 * library Help topic in the Help file.
5279 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5283 BSTR
*pbstrHelpString
,
5284 DWORD
*pdwHelpStringContext
,
5285 BSTR
*pbstrHelpStringDll
)
5287 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5291 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5293 /* the help string should be obtained from the helpstringdll,
5294 * using the _DLLGetDocumentation function, based on the supplied
5295 * lcid. Nice to do sometime...
5299 /* documentation for the typelib */
5301 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5302 if(pdwHelpStringContext
)
5303 *pdwHelpStringContext
=This
->dwHelpContext
;
5304 if(pbstrHelpStringDll
)
5305 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5311 /* for a typeinfo */
5312 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5314 if(SUCCEEDED(result
))
5316 ITypeInfo2
* pTInfo2
;
5317 result
= ITypeInfo_QueryInterface(pTInfo
,
5319 (LPVOID
*) &pTInfo2
);
5321 if(SUCCEEDED(result
))
5323 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5327 pdwHelpStringContext
,
5328 pbstrHelpStringDll
);
5330 ITypeInfo2_Release(pTInfo2
);
5333 ITypeInfo_Release(pTInfo
);
5339 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5341 TLBCustData
*pCData
;
5345 ct
= list_count(custdata_list
);
5347 pCustData
->prgCustData
= heap_alloc_zero(ct
* sizeof(CUSTDATAITEM
));
5348 if(!pCustData
->prgCustData
)
5349 return E_OUTOFMEMORY
;
5351 pCustData
->cCustData
= ct
;
5353 cdi
= pCustData
->prgCustData
;
5354 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5355 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5356 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5364 /* ITypeLib2::GetAllCustData
5366 * Gets all custom data items for the library.
5369 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5371 CUSTDATA
*pCustData
)
5373 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5374 TRACE("(%p)->(%p)\n", This
, pCustData
);
5375 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5378 static const ITypeLib2Vtbl tlbvt
= {
5379 ITypeLib2_fnQueryInterface
,
5381 ITypeLib2_fnRelease
,
5382 ITypeLib2_fnGetTypeInfoCount
,
5383 ITypeLib2_fnGetTypeInfo
,
5384 ITypeLib2_fnGetTypeInfoType
,
5385 ITypeLib2_fnGetTypeInfoOfGuid
,
5386 ITypeLib2_fnGetLibAttr
,
5387 ITypeLib2_fnGetTypeComp
,
5388 ITypeLib2_fnGetDocumentation
,
5390 ITypeLib2_fnFindName
,
5391 ITypeLib2_fnReleaseTLibAttr
,
5393 ITypeLib2_fnGetCustData
,
5394 ITypeLib2_fnGetLibStatistics
,
5395 ITypeLib2_fnGetDocumentation2
,
5396 ITypeLib2_fnGetAllCustData
5400 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5402 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5404 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5407 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5409 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5411 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5414 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5416 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5418 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5421 static HRESULT WINAPI
ITypeLibComp_fnBind(
5426 ITypeInfo
** ppTInfo
,
5427 DESCKIND
* pDescKind
,
5430 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5431 BOOL typemismatch
= FALSE
;
5434 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5436 *pDescKind
= DESCKIND_NONE
;
5437 pBindPtr
->lptcomp
= NULL
;
5440 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5441 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5442 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5444 /* FIXME: check wFlags here? */
5445 /* FIXME: we should use a hash table to look this info up using lHash
5446 * instead of an O(n) search */
5447 if ((pTypeInfo
->typekind
== TKIND_ENUM
) ||
5448 (pTypeInfo
->typekind
== TKIND_MODULE
))
5450 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5452 *pDescKind
= DESCKIND_TYPECOMP
;
5453 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5454 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5455 TRACE("module or enum: %s\n", debugstr_w(szName
));
5460 if ((pTypeInfo
->typekind
== TKIND_MODULE
) ||
5461 (pTypeInfo
->typekind
== TKIND_ENUM
))
5463 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5466 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5467 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5469 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5472 else if (hr
== TYPE_E_TYPEMISMATCH
)
5473 typemismatch
= TRUE
;
5476 if ((pTypeInfo
->typekind
== TKIND_COCLASS
) &&
5477 (pTypeInfo
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5479 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5481 ITypeInfo
*subtypeinfo
;
5483 DESCKIND subdesckind
;
5485 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5486 &subtypeinfo
, &subdesckind
, &subbindptr
);
5487 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5489 TYPEDESC tdesc_appobject
;
5490 const VARDESC vardesc_appobject
=
5493 NULL
, /* lpstrSchema */
5508 VAR_STATIC
/* varkind */
5511 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5512 tdesc_appobject
.vt
= VT_USERDEFINED
;
5514 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5516 /* cleanup things filled in by Bind call so we can put our
5517 * application object data in there instead */
5518 switch (subdesckind
)
5520 case DESCKIND_FUNCDESC
:
5521 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5523 case DESCKIND_VARDESC
:
5524 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5529 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5531 if (pTypeInfo
->hreftype
== -1)
5532 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5534 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5538 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5539 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5540 ITypeInfo_AddRef(*ppTInfo
);
5543 else if (hr
== TYPE_E_TYPEMISMATCH
)
5544 typemismatch
= TRUE
;
5550 TRACE("type mismatch %s\n", debugstr_w(szName
));
5551 return TYPE_E_TYPEMISMATCH
;
5555 TRACE("name not found %s\n", debugstr_w(szName
));
5560 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5564 ITypeInfo
** ppTInfo
,
5565 ITypeComp
** ppTComp
)
5567 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5568 ITypeInfoImpl
*info
;
5570 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5572 if(!szName
|| !ppTInfo
|| !ppTComp
)
5573 return E_INVALIDARG
;
5575 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5582 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5583 ITypeInfo_AddRef(*ppTInfo
);
5584 *ppTComp
= &info
->ITypeComp_iface
;
5585 ITypeComp_AddRef(*ppTComp
);
5590 static const ITypeCompVtbl tlbtcvt
=
5593 ITypeLibComp_fnQueryInterface
,
5594 ITypeLibComp_fnAddRef
,
5595 ITypeLibComp_fnRelease
,
5597 ITypeLibComp_fnBind
,
5598 ITypeLibComp_fnBindType
5601 /*================== ITypeInfo(2) Methods ===================================*/
5602 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5604 ITypeInfoImpl
*pTypeInfoImpl
;
5606 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5609 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5610 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5611 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5612 pTypeInfoImpl
->ref
= 0;
5613 pTypeInfoImpl
->hreftype
= -1;
5614 pTypeInfoImpl
->memidConstructor
= MEMBERID_NIL
;
5615 pTypeInfoImpl
->memidDestructor
= MEMBERID_NIL
;
5616 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5617 list_init(pTypeInfoImpl
->pcustdata_list
);
5619 TRACE("(%p)\n", pTypeInfoImpl
);
5620 return pTypeInfoImpl
;
5623 /* ITypeInfo::QueryInterface
5625 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5630 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5632 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5635 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5636 IsEqualIID(riid
,&IID_ITypeInfo
)||
5637 IsEqualIID(riid
,&IID_ITypeInfo2
))
5639 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5640 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5641 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5644 ITypeInfo2_AddRef(iface
);
5645 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5648 TRACE("-- Interface: E_NOINTERFACE\n");
5649 return E_NOINTERFACE
;
5652 /* ITypeInfo::AddRef
5654 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5656 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5657 ULONG ref
= InterlockedIncrement(&This
->ref
);
5659 TRACE("(%p)->ref is %u\n",This
, ref
);
5661 if (ref
== 1 /* incremented from 0 */)
5662 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5667 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5671 TRACE("destroying ITypeInfo(%p)\n",This
);
5673 for (i
= 0; i
< This
->cFuncs
; ++i
)
5676 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5677 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5679 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5680 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5681 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5682 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5684 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5685 heap_free(pFInfo
->pParamDesc
);
5686 TLB_FreeCustData(&pFInfo
->custdata_list
);
5688 heap_free(This
->funcdescs
);
5690 for(i
= 0; i
< This
->cVars
; ++i
)
5692 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5693 if (pVInfo
->vardesc_create
) {
5694 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5695 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5696 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5697 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5699 TLB_FreeCustData(&pVInfo
->custdata_list
);
5701 heap_free(This
->vardescs
);
5703 if(This
->impltypes
){
5704 for (i
= 0; i
< This
->cImplTypes
; ++i
){
5705 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5706 TLB_FreeCustData(&pImpl
->custdata_list
);
5708 heap_free(This
->impltypes
);
5711 TLB_FreeCustData(&This
->custdata_list
);
5716 /* ITypeInfo::Release
5718 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5720 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5721 ULONG ref
= InterlockedDecrement(&This
->ref
);
5723 TRACE("(%p)->(%u)\n",This
, ref
);
5727 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5728 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5729 if (not_attached_to_typelib
)
5731 /* otherwise This will be freed when typelib is freed */
5737 /* ITypeInfo::GetTypeAttr
5739 * Retrieves a TYPEATTR structure that contains the attributes of the type
5743 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5744 LPTYPEATTR
*ppTypeAttr
)
5746 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5749 TRACE("(%p)\n",This
);
5751 size
= sizeof(**ppTypeAttr
);
5752 if (This
->typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5753 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5755 *ppTypeAttr
= heap_alloc(size
);
5757 return E_OUTOFMEMORY
;
5759 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5760 (*ppTypeAttr
)->lcid
= This
->lcid
;
5761 (*ppTypeAttr
)->memidConstructor
= This
->memidConstructor
;
5762 (*ppTypeAttr
)->memidDestructor
= This
->memidDestructor
;
5763 (*ppTypeAttr
)->lpstrSchema
= This
->lpstrSchema
;
5764 (*ppTypeAttr
)->cbSizeInstance
= This
->cbSizeInstance
;
5765 (*ppTypeAttr
)->typekind
= This
->typekind
;
5766 (*ppTypeAttr
)->cFuncs
= This
->cFuncs
;
5767 (*ppTypeAttr
)->cVars
= This
->cVars
;
5768 (*ppTypeAttr
)->cImplTypes
= This
->cImplTypes
;
5769 (*ppTypeAttr
)->cbSizeVft
= This
->cbSizeVft
;
5770 (*ppTypeAttr
)->cbAlignment
= This
->cbAlignment
;
5771 (*ppTypeAttr
)->wTypeFlags
= This
->wTypeFlags
;
5772 (*ppTypeAttr
)->wMajorVerNum
= This
->wMajorVerNum
;
5773 (*ppTypeAttr
)->wMinorVerNum
= This
->wMinorVerNum
;
5774 (*ppTypeAttr
)->idldescType
= This
->idldescType
;
5776 if (This
->tdescAlias
)
5777 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5778 This
->tdescAlias
, *ppTypeAttr
+ 1);
5780 (*ppTypeAttr
)->tdescAlias
.vt
= VT_EMPTY
;
5781 (*ppTypeAttr
)->tdescAlias
.u
.lptdesc
= NULL
;
5784 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5785 /* This should include all the inherited funcs */
5786 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5787 /* This is always the size of IDispatch's vtbl */
5788 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5789 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5794 /* ITypeInfo::GetTypeComp
5796 * Retrieves the ITypeComp interface for the type description, which enables a
5797 * client compiler to bind to the type description's members.
5800 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5801 ITypeComp
* *ppTComp
)
5803 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5805 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5807 *ppTComp
= &This
->ITypeComp_iface
;
5808 ITypeComp_AddRef(*ppTComp
);
5812 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5814 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5815 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5816 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5820 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5823 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5824 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5826 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5827 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5828 *buffer
+= sizeof(PARAMDESCEX
);
5829 *pparamdescex_dest
= *pparamdescex_src
;
5830 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5831 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5832 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5833 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5836 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5840 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5842 UINT len
= SysStringLen(str
), i
;
5843 for (i
= 0; i
< len
; ++i
)
5849 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5851 if (V_VT(var
) == VT_INT
)
5852 return VariantChangeType(var
, var
, 0, VT_I4
);
5853 else if (V_VT(var
) == VT_UINT
)
5854 return VariantChangeType(var
, var
, 0, VT_UI4
);
5855 else if (V_VT(var
) == VT_BSTR
)
5856 return TLB_SanitizeBSTR(V_BSTR(var
));
5861 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5863 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5864 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5867 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5871 SIZE_T size
= sizeof(*src
);
5875 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5876 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5877 for (i
= 0; i
< src
->cParams
; i
++)
5879 size
+= sizeof(ELEMDESC
);
5880 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5883 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5884 if (!dest
) return E_OUTOFMEMORY
;
5887 if (dispinterface
) /* overwrite funckind */
5888 dest
->funckind
= FUNC_DISPATCH
;
5889 buffer
= (char *)(dest
+ 1);
5891 dest
->oVft
= dest
->oVft
& 0xFFFC;
5893 if (dest
->cScodes
) {
5894 dest
->lprgscode
= (SCODE
*)buffer
;
5895 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5896 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5898 dest
->lprgscode
= NULL
;
5900 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5903 SysFreeString((BSTR
)dest
);
5907 if (dest
->cParams
) {
5908 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5909 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5910 for (i
= 0; i
< src
->cParams
; i
++)
5912 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5918 /* undo the above actions */
5919 for (i
= i
- 1; i
>= 0; i
--)
5920 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5921 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5922 SysFreeString((BSTR
)dest
);
5926 dest
->lprgelemdescParam
= NULL
;
5928 /* special treatment for dispinterfaces: this makes functions appear
5929 * to return their [retval] value when it is really returning an
5931 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5933 if (dest
->cParams
&&
5934 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5936 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5937 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5939 ERR("elemdesc should have started with VT_PTR instead of:\n");
5941 dump_ELEMDESC(elemdesc
);
5942 return E_UNEXPECTED
;
5945 /* copy last parameter to the return value. we are using a flat
5946 * buffer so there is no danger of leaking memory in
5948 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5950 /* remove the last parameter */
5954 /* otherwise this function is made to appear to have no return
5956 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5964 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5966 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5967 if (var_desc
->varkind
== VAR_CONST
)
5968 VariantClear(var_desc
->u
.lpvarValue
);
5969 SysFreeString((BSTR
)var_desc
);
5972 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5974 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5976 if (index
>= This
->cFuncs
)
5977 return TYPE_E_ELEMENTNOTFOUND
;
5979 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5983 /* internal function to make the inherited interfaces' methods appear
5984 * part of the interface */
5985 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5986 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5988 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5990 UINT implemented_funcs
= 0;
5995 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5999 ITypeInfo
*pSubTypeInfo
;
6002 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
6006 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
6009 &sub_funcs
, hrefoffset
);
6010 implemented_funcs
+= sub_funcs
;
6011 ITypeInfo_Release(pSubTypeInfo
);
6014 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
6018 *funcs
= implemented_funcs
+ This
->cFuncs
;
6022 if (index
< implemented_funcs
)
6023 return E_INVALIDARG
;
6024 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
6028 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
6030 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
6033 switch (pTypeDesc
->vt
)
6035 case VT_USERDEFINED
:
6036 pTypeDesc
->u
.hreftype
+= hrefoffset
;
6040 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
6043 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
6051 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
6054 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6055 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
6056 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
6059 /* ITypeInfo::GetFuncDesc
6061 * Retrieves the FUNCDESC structure that contains information about a
6062 * specified function.
6065 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
6066 LPFUNCDESC
*ppFuncDesc
)
6068 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6069 const FUNCDESC
*internal_funcdesc
;
6071 UINT hrefoffset
= 0;
6073 TRACE("(%p) index %d\n", This
, index
);
6076 return E_INVALIDARG
;
6078 if (This
->needs_layout
)
6079 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6081 if (This
->typekind
== TKIND_DISPATCH
)
6082 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
6083 &internal_funcdesc
, NULL
,
6086 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6087 &internal_funcdesc
);
6090 WARN("description for function %d not found\n", index
);
6094 hr
= TLB_AllocAndInitFuncDesc(
6097 This
->typekind
== TKIND_DISPATCH
);
6099 if ((This
->typekind
== TKIND_DISPATCH
) && hrefoffset
)
6100 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6102 TRACE("-- 0x%08x\n", hr
);
6106 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6110 SIZE_T size
= sizeof(*src
);
6113 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6114 if (src
->varkind
== VAR_CONST
)
6115 size
+= sizeof(VARIANT
);
6116 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6118 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6119 if (!dest
) return E_OUTOFMEMORY
;
6122 buffer
= (char *)(dest
+ 1);
6123 if (src
->lpstrSchema
)
6126 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6127 len
= strlenW(src
->lpstrSchema
);
6128 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6129 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6132 if (src
->varkind
== VAR_CONST
)
6136 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6137 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6138 buffer
+= sizeof(VARIANT
);
6139 VariantInit(dest
->u
.lpvarValue
);
6140 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6143 SysFreeString((BSTR
)dest
);
6147 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6150 if (src
->varkind
== VAR_CONST
)
6151 VariantClear(dest
->u
.lpvarValue
);
6152 SysFreeString((BSTR
)dest
);
6159 /* ITypeInfo::GetVarDesc
6161 * Retrieves a VARDESC structure that describes the specified variable.
6164 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6165 LPVARDESC
*ppVarDesc
)
6167 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6168 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6170 TRACE("(%p) index %d\n", This
, index
);
6172 if(index
>= This
->cVars
)
6173 return TYPE_E_ELEMENTNOTFOUND
;
6175 if (This
->needs_layout
)
6176 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6178 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6181 /* ITypeInfo_GetNames
6183 * Retrieves the variable with the specified member ID (or the name of the
6184 * property or method and its parameters) that correspond to the specified
6187 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6188 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6190 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6191 const TLBFuncDesc
*pFDesc
;
6192 const TLBVarDesc
*pVDesc
;
6194 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6197 return E_INVALIDARG
;
6201 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
6204 if(!cMaxNames
|| !pFDesc
->Name
)
6207 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6210 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6211 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6213 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6219 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
6222 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6227 if(This
->impltypes
&&
6228 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
6229 /* recursive search */
6232 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6233 if(SUCCEEDED(result
))
6235 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6236 ITypeInfo_Release(pTInfo
);
6239 WARN("Could not search inherited interface!\n");
6243 WARN("no names found\n");
6246 return TYPE_E_ELEMENTNOTFOUND
;
6252 /* ITypeInfo::GetRefTypeOfImplType
6254 * If a type description describes a COM class, it retrieves the type
6255 * description of the implemented interface types. For an interface,
6256 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6260 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6265 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6268 TRACE("(%p) index %d\n", This
, index
);
6269 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6273 /* only valid on dual interfaces;
6274 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6277 if (This
->wTypeFlags
& TYPEFLAG_FDUAL
)
6283 hr
= TYPE_E_ELEMENTNOTFOUND
;
6286 else if(index
== 0 && This
->typekind
== TKIND_DISPATCH
)
6288 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6289 *pRefType
= This
->pTypeLib
->dispatch_href
;
6293 if(index
>= This
->cImplTypes
)
6294 hr
= TYPE_E_ELEMENTNOTFOUND
;
6296 *pRefType
= This
->impltypes
[index
].hRef
;
6297 if(This
->typekind
== TKIND_INTERFACE
)
6305 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6307 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6313 /* ITypeInfo::GetImplTypeFlags
6315 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6316 * or base interface in a type description.
6318 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6319 UINT index
, INT
*pImplTypeFlags
)
6321 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6323 TRACE("(%p) index %d\n", This
, index
);
6326 return E_INVALIDARG
;
6328 if(This
->typekind
== TKIND_DISPATCH
&& index
== 0){
6329 *pImplTypeFlags
= 0;
6333 if(index
>= This
->cImplTypes
)
6334 return TYPE_E_ELEMENTNOTFOUND
;
6336 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6342 * Maps between member names and member IDs, and parameter names and
6345 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6346 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6348 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6349 const TLBVarDesc
*pVDesc
;
6353 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6356 /* init out parameters in case of failure */
6357 for (i
= 0; i
< cNames
; i
++)
6358 pMemId
[i
] = MEMBERID_NIL
;
6360 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
) {
6362 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6363 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6364 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6365 for(i
=1; i
< cNames
; i
++){
6366 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6367 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6369 if( j
<pFDesc
->funcdesc
.cParams
)
6372 ret
=DISP_E_UNKNOWNNAME
;
6374 TRACE("-- 0x%08x\n", ret
);
6378 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, *rgszNames
);
6381 *pMemId
= pVDesc
->vardesc
.memid
;
6384 /* not found, see if it can be found in an inherited interface */
6385 if(This
->impltypes
) {
6386 /* recursive search */
6388 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6390 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6391 ITypeInfo_Release(pTInfo
);
6394 WARN("Could not search inherited interface!\n");
6396 WARN("no names found\n");
6397 return DISP_E_UNKNOWNNAME
;
6403 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6404 __ASM_GLOBAL_FUNC( call_method
,
6406 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6407 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6408 "movl %esp,%ebp\n\t"
6409 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6411 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6413 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6414 "movl 12(%ebp),%edx\n\t"
6415 "movl %esp,%edi\n\t"
6418 "subl %edx,%edi\n\t"
6419 "andl $~15,%edi\n\t"
6420 "movl %edi,%esp\n\t"
6421 "movl 12(%ebp),%ecx\n\t"
6422 "movl 16(%ebp),%esi\n\t"
6425 "1:\tcall *8(%ebp)\n\t"
6426 "subl %esp,%edi\n\t"
6427 "movl 20(%ebp),%ecx\n\t"
6428 "movl %edi,(%ecx)\n\t"
6429 "leal -8(%ebp),%esp\n\t"
6431 __ASM_CFI(".cfi_same_value %edi\n\t")
6433 __ASM_CFI(".cfi_same_value %esi\n\t")
6435 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6436 __ASM_CFI(".cfi_same_value %ebp\n\t")
6439 /* same function but returning floating point */
6440 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6442 /* ITypeInfo::Invoke
6444 * Invokes a method, or accesses a property of an object, that implements the
6445 * interface described by the type description.
6448 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6452 if (TRACE_ON(ole
)) {
6454 TRACE("Calling %p(",func
);
6455 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6456 if (nrargs
> 30) TRACE("...");
6463 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6466 FIXME("unsupported calling convention %d\n",callconv
);
6470 TRACE("returns %08x\n",res
);
6474 #elif defined(__x86_64__)
6476 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6477 __ASM_GLOBAL_FUNC( call_method
,
6479 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6480 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6481 "movq %rsp,%rbp\n\t"
6482 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6484 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6486 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6487 "movq %rcx,%rax\n\t"
6490 "cmovgq %rdx,%rcx\n\t"
6491 "leaq 0(,%rcx,8),%rdx\n\t"
6492 "subq %rdx,%rsp\n\t"
6493 "andq $~15,%rsp\n\t"
6494 "movq %rsp,%rdi\n\t"
6497 "movq 0(%rsp),%rcx\n\t"
6498 "movq 8(%rsp),%rdx\n\t"
6499 "movq 16(%rsp),%r8\n\t"
6500 "movq 24(%rsp),%r9\n\t"
6501 "movq %rcx,%xmm0\n\t"
6502 "movq %rdx,%xmm1\n\t"
6503 "movq %r8,%xmm2\n\t"
6504 "movq %r9,%xmm3\n\t"
6506 "leaq -16(%rbp),%rsp\n\t"
6508 __ASM_CFI(".cfi_same_value %rdi\n\t")
6510 __ASM_CFI(".cfi_same_value %rsi\n\t")
6511 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6513 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6514 __ASM_CFI(".cfi_same_value %rbp\n\t")
6517 /* same function but returning floating point */
6518 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6520 #endif /* __x86_64__ */
6522 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6525 ITypeInfo
*tinfo2
= NULL
;
6526 TYPEATTR
*tattr
= NULL
;
6528 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6531 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6533 tdesc
->u
.hreftype
, hr
);
6536 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6539 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6540 ITypeInfo_Release(tinfo2
);
6544 switch (tattr
->typekind
)
6551 tdesc
= &tattr
->tdescAlias
;
6552 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6555 case TKIND_INTERFACE
:
6556 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6562 case TKIND_DISPATCH
:
6571 FIXME("TKIND_RECORD unhandled.\n");
6576 FIXME("TKIND_UNION unhandled.\n");
6581 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6585 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6586 ITypeInfo_Release(tinfo2
);
6590 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6594 /* enforce only one level of pointer indirection */
6595 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6597 tdesc
= tdesc
->u
.lptdesc
;
6599 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6600 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6601 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6602 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6603 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6605 VARTYPE vt_userdefined
= 0;
6606 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6607 if (tdesc
->vt
== VT_PTR
)
6609 vt_userdefined
= VT_BYREF
;
6610 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6612 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6614 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6615 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6617 *vt
|= vt_userdefined
;
6629 case VT_USERDEFINED
:
6630 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6637 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6638 hr
= DISP_E_BADVARTYPE
;
6642 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6657 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6663 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6667 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6669 ITypeInfo_Release(tinfo2
);
6673 switch(tattr
->typekind
) {
6675 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6678 case TKIND_INTERFACE
:
6679 case TKIND_DISPATCH
:
6680 *guid
= tattr
->guid
;
6684 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6685 hres
= E_UNEXPECTED
;
6688 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6689 ITypeInfo_Release(tinfo2
);
6693 /***********************************************************************
6694 * DispCallFunc (OLEAUT32.@)
6696 * Invokes a function of the specified calling convention, passing the
6697 * specified arguments and returns the result.
6700 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6701 * oVft [I] The offset in the vtable. See notes.
6702 * cc [I] Calling convention of the function to call.
6703 * vtReturn [I] The return type of the function.
6704 * cActuals [I] Number of parameters.
6705 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6706 * prgpvarg [I] The arguments to pass.
6707 * pvargResult [O] The return value of the function. Can be NULL.
6711 * Failure: HRESULT code.
6714 * The HRESULT return value of this function is not affected by the return
6715 * value of the user supplied function, which is returned in pvargResult.
6717 * If pvInstance is NULL then a non-object function is to be called and oVft
6718 * is the address of the function to call.
6720 * The cc parameter can be one of the following values:
6733 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6734 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6737 int argspos
, stack_offset
;
6742 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6743 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6744 pvargResult
, V_VT(pvargResult
));
6746 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6748 FIXME("unsupported calling convention %d\n",cc
);
6749 return E_INVALIDARG
;
6752 /* maximum size for an argument is sizeof(VARIANT) */
6753 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6755 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6759 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6760 func
= vtable
[oVft
/sizeof(void *)];
6761 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6763 else func
= (void *)oVft
;
6765 for (i
= 0; i
< cActuals
; i
++)
6767 VARIANT
*arg
= prgpvarg
[i
];
6778 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6779 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6783 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6784 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6786 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6787 args
[argspos
++] = V_BOOL(arg
);
6790 args
[argspos
++] = V_UI4(arg
);
6793 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6800 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6803 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6807 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6811 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6812 call_method( func
, argspos
, args
, &stack_offset
);
6817 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6820 WARN("invalid return type %u\n", vtReturn
);
6822 return E_INVALIDARG
;
6824 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6828 if (stack_offset
&& cc
== CC_STDCALL
)
6830 WARN( "stack pointer off by %d\n", stack_offset
);
6831 return DISP_E_BADCALLEE
;
6833 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6834 TRACE("retval: "); dump_Variant(pvargResult
);
6837 #elif defined(__x86_64__)
6843 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6844 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6845 pvargResult
, V_VT(pvargResult
));
6847 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6849 FIXME("unsupported calling convention %d\n",cc
);
6850 return E_INVALIDARG
;
6853 /* maximum size for an argument is sizeof(DWORD_PTR) */
6854 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6856 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6860 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6861 func
= vtable
[oVft
/sizeof(void *)];
6862 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6864 else func
= (void *)oVft
;
6866 for (i
= 0; i
< cActuals
; i
++)
6868 VARIANT
*arg
= prgpvarg
[i
];
6874 args
[argspos
++] = (ULONG_PTR
)arg
;
6876 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6877 args
[argspos
++] = V_BOOL(arg
);
6880 args
[argspos
++] = V_UI8(arg
);
6883 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6890 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6894 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6898 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6899 call_method( func
, argspos
, args
);
6902 WARN("invalid return type %u\n", vtReturn
);
6904 return E_INVALIDARG
;
6906 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6910 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6911 TRACE("retval: "); dump_Variant(pvargResult
);
6915 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6916 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6921 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6923 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6926 #define INVBUF_ELEMENT_SIZE \
6927 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6928 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6929 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6930 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6931 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6932 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6933 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6934 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6936 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6941 DISPPARAMS
*pDispParams
,
6942 VARIANT
*pVarResult
,
6943 EXCEPINFO
*pExcepInfo
,
6946 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6948 unsigned int var_index
;
6951 const TLBFuncDesc
*pFuncInfo
;
6954 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6955 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6958 if( This
->wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6959 return DISP_E_MEMBERNOTFOUND
;
6963 ERR("NULL pDispParams not allowed\n");
6964 return E_INVALIDARG
;
6967 dump_DispParms(pDispParams
);
6969 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6971 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6972 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6973 return E_INVALIDARG
;
6976 /* we do this instead of using GetFuncDesc since it will return a fake
6977 * FUNCDESC for dispinterfaces and we want the real function description */
6978 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
6979 pFuncInfo
= &This
->funcdescs
[fdc
];
6980 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6981 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6982 !func_restricted( &pFuncInfo
->funcdesc
))
6986 if (fdc
< This
->cFuncs
) {
6987 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6991 TRACE("invoking:\n");
6992 dump_TLBFuncDescOne(pFuncInfo
);
6995 switch (func_desc
->funckind
) {
6996 case FUNC_PUREVIRTUAL
:
6997 case FUNC_VIRTUAL
: {
6998 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7000 VARIANT retval
; /* pointer for storing byref retvals in */
7001 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7002 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7003 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7004 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7005 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7006 UINT vargs_converted
=0;
7010 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7012 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7014 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7015 hres
= DISP_E_PARAMNOTFOUND
;
7020 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7022 ERR("functions with the vararg attribute do not support named arguments\n");
7023 hres
= DISP_E_NONAMEDARGS
;
7027 for (i
= 0; i
< func_desc
->cParams
; i
++)
7029 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7030 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7035 TRACE("changing args\n");
7036 for (i
= 0; i
< func_desc
->cParams
; i
++)
7038 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7039 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7040 VARIANTARG
*src_arg
;
7042 if (wParamFlags
& PARAMFLAG_FLCID
)
7045 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7047 V_I4(arg
) = This
->pTypeLib
->lcid
;
7056 for (j
= 0; j
< cNamedArgs
; j
++)
7057 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7059 src_arg
= &pDispParams
->rgvarg
[j
];
7064 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7066 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7070 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7072 /* under most conditions the caller is not allowed to
7073 * pass in a dispparam arg in the index of what would be
7074 * the retval parameter. however, there is an exception
7075 * where the extra parameter is used in an extra
7076 * IDispatch::Invoke below */
7077 if ((i
< pDispParams
->cArgs
) &&
7078 ((func_desc
->cParams
!= 1) || !pVarResult
||
7079 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7081 hres
= DISP_E_BADPARAMCOUNT
;
7085 /* note: this check is placed so that if the caller passes
7086 * in a VARIANTARG for the retval we just ignore it, like
7088 if (i
== func_desc
->cParams
- 1)
7091 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7092 memset(arg
, 0, sizeof(*arg
));
7093 V_VT(arg
) = rgvt
[i
];
7094 memset(&retval
, 0, sizeof(retval
));
7095 V_BYREF(arg
) = &retval
;
7099 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7100 hres
= E_UNEXPECTED
;
7106 dump_Variant(src_arg
);
7108 if(rgvt
[i
]!=V_VT(src_arg
))
7110 if (rgvt
[i
] == VT_VARIANT
)
7111 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7112 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7114 if (rgvt
[i
] == V_VT(src_arg
))
7115 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7118 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7119 if (wParamFlags
& PARAMFLAG_FIN
)
7120 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7121 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7123 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7125 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
7128 SAFEARRAYBOUND bound
;
7132 bound
.cElements
= pDispParams
->cArgs
-i
;
7133 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7135 ERR("SafeArrayCreate failed\n");
7138 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7141 ERR("SafeArrayAccessData failed with %x\n", hres
);
7142 SafeArrayDestroy(a
);
7145 for (j
= 0; j
< bound
.cElements
; j
++)
7146 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7147 hres
= SafeArrayUnaccessData(a
);
7150 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7151 SafeArrayDestroy(a
);
7154 V_ARRAY(&rgvarg
[i
]) = a
;
7155 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7157 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7159 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7160 if (wParamFlags
& PARAMFLAG_FIN
)
7161 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7163 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7164 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7165 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7167 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7169 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7170 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7174 /* FIXME: this doesn't work for VT_BYREF arguments if
7175 * they are not the same type as in the paramdesc */
7176 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7177 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7178 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7183 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
7184 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
7185 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
7188 prgpvarg
[i
] = &rgvarg
[i
];
7192 prgpvarg
[i
] = src_arg
;
7195 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7196 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7197 && V_UNKNOWN(prgpvarg
[i
])) {
7198 IUnknown
*userdefined_iface
;
7201 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7205 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7207 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7211 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7212 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7215 else if (wParamFlags
& PARAMFLAG_FOPT
)
7218 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7219 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7221 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7227 VARIANTARG
*missing_arg
;
7228 /* if the function wants a pointer to a variant then
7229 * set that up, otherwise just pass the VT_ERROR in
7230 * the argument by value */
7231 if (rgvt
[i
] & VT_BYREF
)
7233 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7234 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7235 V_VARIANTREF(arg
) = missing_arg
;
7239 V_VT(missing_arg
) = VT_ERROR
;
7240 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7245 hres
= DISP_E_BADPARAMCOUNT
;
7249 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7251 /* VT_VOID is a special case for return types, so it is not
7252 * handled in the general function */
7253 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7254 V_VT(&varresult
) = VT_EMPTY
;
7257 V_VT(&varresult
) = 0;
7258 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7259 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7262 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7263 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7264 prgpvarg
, &varresult
);
7266 vargs_converted
= 0;
7268 for (i
= 0; i
< func_desc
->cParams
; i
++)
7270 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7271 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7273 if (wParamFlags
& PARAMFLAG_FLCID
)
7275 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7279 TRACE("[retval] value: ");
7280 dump_Variant(prgpvarg
[i
]);
7285 VariantInit(pVarResult
);
7286 /* deref return value */
7287 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7290 VARIANT_ClearInd(prgpvarg
[i
]);
7292 else if (vargs_converted
< pDispParams
->cArgs
)
7294 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7295 if (wParamFlags
& PARAMFLAG_FOUT
)
7297 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7299 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7303 ERR("failed to convert param %d to vt %d\n", i
,
7304 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7309 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7310 func_desc
->cParamsOpt
< 0 &&
7311 i
== func_desc
->cParams
-1)
7313 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7316 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7319 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7322 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7325 ERR("SafeArrayAccessData failed with %x\n", hres
);
7328 for (j
= 0; j
<= ubound
; j
++)
7329 VariantClear(&v
[j
]);
7330 hres
= SafeArrayUnaccessData(a
);
7333 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7337 VariantClear(&rgvarg
[i
]);
7340 else if (wParamFlags
& PARAMFLAG_FOPT
)
7342 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7343 VariantClear(&rgvarg
[i
]);
7346 VariantClear(&missing_arg
[i
]);
7349 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7351 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7352 hres
= DISP_E_EXCEPTION
;
7355 IErrorInfo
*pErrorInfo
;
7356 pExcepInfo
->scode
= V_ERROR(&varresult
);
7357 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7359 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7360 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7361 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7362 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7364 IErrorInfo_Release(pErrorInfo
);
7368 if (V_VT(&varresult
) != VT_ERROR
)
7370 TRACE("varresult value: ");
7371 dump_Variant(&varresult
);
7375 VariantClear(pVarResult
);
7376 *pVarResult
= varresult
;
7379 VariantClear(&varresult
);
7382 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7383 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7384 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7385 (pDispParams
->cArgs
!= 0))
7387 if (V_VT(pVarResult
) == VT_DISPATCH
)
7389 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7390 /* Note: not VariantClear; we still need the dispatch
7391 * pointer to be valid */
7392 VariantInit(pVarResult
);
7393 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7394 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7395 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7396 IDispatch_Release(pDispatch
);
7400 VariantClear(pVarResult
);
7401 hres
= DISP_E_NOTACOLLECTION
;
7409 case FUNC_DISPATCH
: {
7412 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7413 if (SUCCEEDED(hres
)) {
7414 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7415 hres
= IDispatch_Invoke(
7416 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7417 pVarResult
,pExcepInfo
,pArgErr
7420 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7421 IDispatch_Release(disp
);
7423 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7427 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7432 TRACE("-- 0x%08x\n", hres
);
7435 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7438 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7439 if(FAILED(hres
)) return hres
;
7441 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7442 dump_VARDESC(var_desc
);
7443 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7447 /* not found, look for it in inherited interfaces */
7448 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7449 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7450 if(This
->impltypes
) {
7451 /* recursive search */
7453 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7454 if(SUCCEEDED(hres
)){
7455 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7456 ITypeInfo_Release(pTInfo
);
7459 WARN("Could not search inherited interface!\n");
7462 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7463 return DISP_E_MEMBERNOTFOUND
;
7466 /* ITypeInfo::GetDocumentation
7468 * Retrieves the documentation string, the complete Help file name and path,
7469 * and the context ID for the Help topic for a specified type description.
7471 * (Can be tested by the Visual Basic Editor in Word for instance.)
7473 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7474 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7475 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7477 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7478 const TLBFuncDesc
*pFDesc
;
7479 const TLBVarDesc
*pVDesc
;
7480 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7481 " HelpContext(%p) HelpFile(%p)\n",
7482 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7483 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7485 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7487 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7489 *pdwHelpContext
=This
->dwHelpContext
;
7491 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7493 }else {/* for a member */
7494 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7497 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7499 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7501 *pdwHelpContext
=pFDesc
->helpcontext
;
7503 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7506 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7509 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7511 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7513 *pdwHelpContext
=pVDesc
->HelpContext
;
7515 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7520 if(This
->impltypes
&&
7521 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
7522 /* recursive search */
7525 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7526 if(SUCCEEDED(result
)) {
7527 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7528 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7529 ITypeInfo_Release(pTInfo
);
7532 WARN("Could not search inherited interface!\n");
7535 WARN("member %d not found\n", memid
);
7536 return TYPE_E_ELEMENTNOTFOUND
;
7539 /* ITypeInfo::GetDllEntry
7541 * Retrieves a description or specification of an entry point for a function
7544 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7545 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7548 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7549 const TLBFuncDesc
*pFDesc
;
7551 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7553 if (pBstrDllName
) *pBstrDllName
= NULL
;
7554 if (pBstrName
) *pBstrName
= NULL
;
7555 if (pwOrdinal
) *pwOrdinal
= 0;
7557 if (This
->typekind
!= TKIND_MODULE
)
7558 return TYPE_E_BADMODULEKIND
;
7560 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7562 dump_TypeInfo(This
);
7564 dump_TLBFuncDescOne(pFDesc
);
7567 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7569 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7571 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7579 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7582 return TYPE_E_ELEMENTNOTFOUND
;
7585 /* internal function to make the inherited interfaces' methods appear
7586 * part of the interface */
7587 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7588 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7590 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7593 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7595 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7597 ITypeInfo
*pSubTypeInfo
;
7599 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7603 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7605 ITypeInfo_Release(pSubTypeInfo
);
7609 *hRefType
-= DISPATCH_HREF_OFFSET
;
7611 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7612 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7617 /* ITypeInfo::GetRefTypeInfo
7619 * If a type description references other type descriptions, it retrieves
7620 * the referenced type descriptions.
7622 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7625 ITypeInfo
**ppTInfo
)
7627 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7628 HRESULT result
= E_FAIL
;
7631 return E_INVALIDARG
;
7633 if ((INT
)hRefType
< 0) {
7634 ITypeInfoImpl
*pTypeInfoImpl
;
7636 if (!(This
->wTypeFlags
& TYPEFLAG_FDUAL
) ||
7637 !(This
->typekind
== TKIND_INTERFACE
||
7638 This
->typekind
== TKIND_DISPATCH
))
7639 return TYPE_E_ELEMENTNOTFOUND
;
7641 /* when we meet a DUAL typeinfo, we must create the alternate
7644 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7646 *pTypeInfoImpl
= *This
;
7647 pTypeInfoImpl
->ref
= 0;
7648 list_init(&pTypeInfoImpl
->custdata_list
);
7650 if (This
->typekind
== TKIND_INTERFACE
)
7651 pTypeInfoImpl
->typekind
= TKIND_DISPATCH
;
7653 pTypeInfoImpl
->typekind
= TKIND_INTERFACE
;
7655 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7656 /* the AddRef implicitly adds a reference to the parent typelib, which
7657 * stops the copied data from being destroyed until the new typeinfo's
7658 * refcount goes to zero, but we need to signal to the new instance to
7659 * not free its data structures when it is destroyed */
7660 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7662 ITypeInfo_AddRef(*ppTInfo
);
7665 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7666 (This
->typekind
== TKIND_DISPATCH
))
7668 HREFTYPE href_dispatch
= hRefType
;
7669 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7671 TLBRefType
*ref_type
;
7672 ITypeLib
*pTLib
= NULL
;
7675 if(!(hRefType
& 0x1)){
7676 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7678 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7681 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7682 ITypeInfo_AddRef(*ppTInfo
);
7688 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7690 if(ref_type
->reference
== (hRefType
& (~0x3)))
7693 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7695 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7699 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7701 TRACE("internal reference\n");
7702 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7704 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7705 TRACE("typeinfo in imported typelib that is already loaded\n");
7706 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7707 ITypeLib_AddRef(pTLib
);
7712 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7714 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7715 ref_type
->pImpTLInfo
->wVersionMajor
,
7716 ref_type
->pImpTLInfo
->wVersionMinor
,
7717 This
->pTypeLib
->syskind
,
7718 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7720 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7722 result
= LoadTypeLib(libnam
, &pTLib
);
7723 SysFreeString(libnam
);
7725 if(SUCCEEDED(result
)) {
7726 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7727 ITypeLib_AddRef(pTLib
);
7731 if(SUCCEEDED(result
)) {
7732 if(ref_type
->index
== TLB_REF_USE_GUID
)
7733 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7735 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7738 ITypeLib_Release(pTLib
);
7742 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7743 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7747 /* ITypeInfo::AddressOfMember
7749 * Retrieves the addresses of static functions or variables, such as those
7752 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7753 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7755 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7761 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7763 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7767 module
= LoadLibraryW(dll
);
7770 ERR("couldn't load %s\n", debugstr_w(dll
));
7772 SysFreeString(entry
);
7773 return STG_E_FILENOTFOUND
;
7775 /* FIXME: store library somewhere where we can free it */
7780 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7781 entryA
= heap_alloc(len
);
7782 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7784 *ppv
= GetProcAddress(module
, entryA
);
7786 ERR("function not found %s\n", debugstr_a(entryA
));
7792 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7794 ERR("function not found %d\n", ordinal
);
7798 SysFreeString(entry
);
7801 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7806 /* ITypeInfo::CreateInstance
7808 * Creates a new instance of a type that describes a component object class
7811 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7812 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7814 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7818 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7824 WARN("Not able to aggregate\n");
7825 return CLASS_E_NOAGGREGATION
;
7828 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7829 if(FAILED(hr
)) return hr
;
7831 if(pTA
->typekind
!= TKIND_COCLASS
)
7833 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7839 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7842 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7843 TRACE("GetActiveObject rets %08x\n", hr
);
7846 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7847 IUnknown_Release(pUnk
);
7852 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7853 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7857 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7861 /* ITypeInfo::GetMops
7863 * Retrieves marshalling information.
7865 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7868 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7869 FIXME("(%p %d) stub!\n", This
, memid
);
7874 /* ITypeInfo::GetContainingTypeLib
7876 * Retrieves the containing type library and the index of the type description
7877 * within that type library.
7879 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7880 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7882 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7884 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7886 *pIndex
=This
->index
;
7887 TRACE("returning pIndex=%d\n", *pIndex
);
7891 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7892 ITypeLib_AddRef(*ppTLib
);
7893 TRACE("returning ppTLib=%p\n", *ppTLib
);
7899 /* ITypeInfo::ReleaseTypeAttr
7901 * Releases a TYPEATTR previously returned by Get
7904 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7905 TYPEATTR
* pTypeAttr
)
7907 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7908 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7909 heap_free(pTypeAttr
);
7912 /* ITypeInfo::ReleaseFuncDesc
7914 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7916 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7918 FUNCDESC
*pFuncDesc
)
7920 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7923 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7925 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7926 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7927 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7929 SysFreeString((BSTR
)pFuncDesc
);
7932 /* ITypeInfo::ReleaseVarDesc
7934 * Releases a VARDESC previously returned by GetVarDesc.
7936 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7939 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7940 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7942 TLB_FreeVarDesc(pVarDesc
);
7945 /* ITypeInfo2::GetTypeKind
7947 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7950 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7951 TYPEKIND
*pTypeKind
)
7953 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7954 *pTypeKind
=This
->typekind
;
7955 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7959 /* ITypeInfo2::GetTypeFlags
7961 * Returns the type flags without any allocations. This returns a DWORD type
7962 * flag, which expands the type flags without growing the TYPEATTR (type
7966 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7968 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7969 *pTypeFlags
=This
->wTypeFlags
;
7970 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7974 /* ITypeInfo2::GetFuncIndexOfMemId
7975 * Binds to a specific member based on a known DISPID, where the member name
7976 * is not known (for example, when binding to a default member).
7979 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7980 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7982 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7986 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
7987 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7988 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7991 if(fdc
< This
->cFuncs
) {
7995 result
= TYPE_E_ELEMENTNOTFOUND
;
7997 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7998 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8002 /* TypeInfo2::GetVarIndexOfMemId
8004 * Binds to a specific member based on a known DISPID, where the member name
8005 * is not known (for example, when binding to a default member).
8008 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8009 MEMBERID memid
, UINT
*pVarIndex
)
8011 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8012 TLBVarDesc
*pVarInfo
;
8014 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8016 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8018 return TYPE_E_ELEMENTNOTFOUND
;
8020 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8025 /* ITypeInfo2::GetCustData
8027 * Gets the custom data
8029 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8034 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8035 TLBCustData
*pCData
;
8037 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8039 if(!guid
|| !pVarVal
)
8040 return E_INVALIDARG
;
8042 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8044 VariantInit( pVarVal
);
8046 VariantCopy( pVarVal
, &pCData
->data
);
8048 VariantClear( pVarVal
);
8052 /* ITypeInfo2::GetFuncCustData
8054 * Gets the custom data
8056 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8062 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8063 TLBCustData
*pCData
;
8064 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8066 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8068 if(index
>= This
->cFuncs
)
8069 return TYPE_E_ELEMENTNOTFOUND
;
8071 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8073 return TYPE_E_ELEMENTNOTFOUND
;
8075 VariantInit(pVarVal
);
8076 VariantCopy(pVarVal
, &pCData
->data
);
8081 /* ITypeInfo2::GetParamCustData
8083 * Gets the custom data
8085 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8092 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8093 TLBCustData
*pCData
;
8094 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8096 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8097 debugstr_guid(guid
), pVarVal
);
8099 if(indexFunc
>= This
->cFuncs
)
8100 return TYPE_E_ELEMENTNOTFOUND
;
8102 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8103 return TYPE_E_ELEMENTNOTFOUND
;
8105 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8107 return TYPE_E_ELEMENTNOTFOUND
;
8109 VariantInit(pVarVal
);
8110 VariantCopy(pVarVal
, &pCData
->data
);
8115 /* ITypeInfo2::GetVarCustData
8117 * Gets the custom data
8119 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8125 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8126 TLBCustData
*pCData
;
8127 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8129 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8131 if(index
>= This
->cVars
)
8132 return TYPE_E_ELEMENTNOTFOUND
;
8134 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8136 return TYPE_E_ELEMENTNOTFOUND
;
8138 VariantInit(pVarVal
);
8139 VariantCopy(pVarVal
, &pCData
->data
);
8144 /* ITypeInfo2::GetImplCustData
8146 * Gets the custom data
8148 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8154 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8155 TLBCustData
*pCData
;
8156 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8158 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8160 if(index
>= This
->cImplTypes
)
8161 return TYPE_E_ELEMENTNOTFOUND
;
8163 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8165 return TYPE_E_ELEMENTNOTFOUND
;
8167 VariantInit(pVarVal
);
8168 VariantCopy(pVarVal
, &pCData
->data
);
8173 /* ITypeInfo2::GetDocumentation2
8175 * Retrieves the documentation string, the complete Help file name and path,
8176 * the localization context to use, and the context ID for the library Help
8177 * topic in the Help file.
8180 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8184 BSTR
*pbstrHelpString
,
8185 DWORD
*pdwHelpStringContext
,
8186 BSTR
*pbstrHelpStringDll
)
8188 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8189 const TLBFuncDesc
*pFDesc
;
8190 const TLBVarDesc
*pVDesc
;
8191 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8192 "HelpStringContext(%p) HelpStringDll(%p)\n",
8193 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8194 pbstrHelpStringDll
);
8195 /* the help string should be obtained from the helpstringdll,
8196 * using the _DLLGetDocumentation function, based on the supplied
8197 * lcid. Nice to do sometime...
8199 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8201 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8202 if(pdwHelpStringContext
)
8203 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8204 if(pbstrHelpStringDll
)
8205 *pbstrHelpStringDll
=
8206 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8208 }else {/* for a member */
8209 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
8212 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8213 if(pdwHelpStringContext
)
8214 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8215 if(pbstrHelpStringDll
)
8216 *pbstrHelpStringDll
=
8217 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8220 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8223 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8224 if(pdwHelpStringContext
)
8225 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8226 if(pbstrHelpStringDll
)
8227 *pbstrHelpStringDll
=
8228 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8232 return TYPE_E_ELEMENTNOTFOUND
;
8235 /* ITypeInfo2::GetAllCustData
8237 * Gets all custom data items for the Type info.
8240 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8242 CUSTDATA
*pCustData
)
8244 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8246 TRACE("%p %p\n", This
, pCustData
);
8248 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8251 /* ITypeInfo2::GetAllFuncCustData
8253 * Gets all custom data items for the specified Function
8256 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8259 CUSTDATA
*pCustData
)
8261 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8262 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8264 TRACE("%p %u %p\n", This
, index
, pCustData
);
8266 if(index
>= This
->cFuncs
)
8267 return TYPE_E_ELEMENTNOTFOUND
;
8269 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8272 /* ITypeInfo2::GetAllParamCustData
8274 * Gets all custom data items for the Functions
8277 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8278 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8280 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8281 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8283 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8285 if(indexFunc
>= This
->cFuncs
)
8286 return TYPE_E_ELEMENTNOTFOUND
;
8288 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8289 return TYPE_E_ELEMENTNOTFOUND
;
8291 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8294 /* ITypeInfo2::GetAllVarCustData
8296 * Gets all custom data items for the specified Variable
8299 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8300 UINT index
, CUSTDATA
*pCustData
)
8302 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8303 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8305 TRACE("%p %u %p\n", This
, index
, pCustData
);
8307 if(index
>= This
->cVars
)
8308 return TYPE_E_ELEMENTNOTFOUND
;
8310 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8313 /* ITypeInfo2::GetAllImplCustData
8315 * Gets all custom data items for the specified implementation type
8318 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8321 CUSTDATA
*pCustData
)
8323 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8324 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8326 TRACE("%p %u %p\n", This
, index
, pCustData
);
8328 if(index
>= This
->cImplTypes
)
8329 return TYPE_E_ELEMENTNOTFOUND
;
8331 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8334 static const ITypeInfo2Vtbl tinfvt
=
8337 ITypeInfo_fnQueryInterface
,
8339 ITypeInfo_fnRelease
,
8341 ITypeInfo_fnGetTypeAttr
,
8342 ITypeInfo_fnGetTypeComp
,
8343 ITypeInfo_fnGetFuncDesc
,
8344 ITypeInfo_fnGetVarDesc
,
8345 ITypeInfo_fnGetNames
,
8346 ITypeInfo_fnGetRefTypeOfImplType
,
8347 ITypeInfo_fnGetImplTypeFlags
,
8348 ITypeInfo_fnGetIDsOfNames
,
8350 ITypeInfo_fnGetDocumentation
,
8351 ITypeInfo_fnGetDllEntry
,
8352 ITypeInfo_fnGetRefTypeInfo
,
8353 ITypeInfo_fnAddressOfMember
,
8354 ITypeInfo_fnCreateInstance
,
8355 ITypeInfo_fnGetMops
,
8356 ITypeInfo_fnGetContainingTypeLib
,
8357 ITypeInfo_fnReleaseTypeAttr
,
8358 ITypeInfo_fnReleaseFuncDesc
,
8359 ITypeInfo_fnReleaseVarDesc
,
8361 ITypeInfo2_fnGetTypeKind
,
8362 ITypeInfo2_fnGetTypeFlags
,
8363 ITypeInfo2_fnGetFuncIndexOfMemId
,
8364 ITypeInfo2_fnGetVarIndexOfMemId
,
8365 ITypeInfo2_fnGetCustData
,
8366 ITypeInfo2_fnGetFuncCustData
,
8367 ITypeInfo2_fnGetParamCustData
,
8368 ITypeInfo2_fnGetVarCustData
,
8369 ITypeInfo2_fnGetImplTypeCustData
,
8370 ITypeInfo2_fnGetDocumentation2
,
8371 ITypeInfo2_fnGetAllCustData
,
8372 ITypeInfo2_fnGetAllFuncCustData
,
8373 ITypeInfo2_fnGetAllParamCustData
,
8374 ITypeInfo2_fnGetAllVarCustData
,
8375 ITypeInfo2_fnGetAllImplTypeCustData
,
8378 /******************************************************************************
8379 * CreateDispTypeInfo [OLEAUT32.31]
8381 * Build type information for an object so it can be called through an
8382 * IDispatch interface.
8385 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8386 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8389 * This call allows an objects methods to be accessed through IDispatch, by
8390 * building an ITypeInfo object that IDispatch can use to call through.
8392 HRESULT WINAPI
CreateDispTypeInfo(
8393 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8394 LCID lcid
, /* [I] Locale Id */
8395 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8397 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8398 ITypeLibImpl
*pTypeLibImpl
;
8399 unsigned int param
, func
;
8400 TLBFuncDesc
*pFuncDesc
;
8404 pTypeLibImpl
= TypeLibImpl_Constructor();
8405 if (!pTypeLibImpl
) return E_FAIL
;
8407 pTypeLibImpl
->TypeInfoCount
= 2;
8408 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8410 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8411 pTIIface
->pTypeLib
= pTypeLibImpl
;
8412 pTIIface
->index
= 0;
8413 pTIIface
->Name
= NULL
;
8414 pTIIface
->dwHelpContext
= -1;
8415 pTIIface
->guid
= NULL
;
8416 pTIIface
->lcid
= lcid
;
8417 pTIIface
->typekind
= TKIND_INTERFACE
;
8418 pTIIface
->wMajorVerNum
= 0;
8419 pTIIface
->wMinorVerNum
= 0;
8420 pTIIface
->cbAlignment
= 2;
8421 pTIIface
->cbSizeInstance
= -1;
8422 pTIIface
->cbSizeVft
= -1;
8423 pTIIface
->cFuncs
= 0;
8424 pTIIface
->cImplTypes
= 0;
8425 pTIIface
->cVars
= 0;
8426 pTIIface
->wTypeFlags
= 0;
8427 pTIIface
->hreftype
= 0;
8429 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8430 pFuncDesc
= pTIIface
->funcdescs
;
8431 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8432 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8433 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8434 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8435 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8436 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8437 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8438 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8439 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8440 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8441 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8442 pFuncDesc
->funcdesc
.cScodes
= 0;
8443 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8444 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8445 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8446 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8447 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8448 md
->cArgs
* sizeof(ELEMDESC
));
8449 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8450 for(param
= 0; param
< md
->cArgs
; param
++) {
8451 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8452 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8454 pFuncDesc
->helpcontext
= 0;
8455 pFuncDesc
->HelpStringContext
= 0;
8456 pFuncDesc
->HelpString
= NULL
;
8457 pFuncDesc
->Entry
= NULL
;
8458 list_init(&pFuncDesc
->custdata_list
);
8463 dump_TypeInfo(pTIIface
);
8465 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8466 pTIClass
->pTypeLib
= pTypeLibImpl
;
8467 pTIClass
->index
= 1;
8468 pTIClass
->Name
= NULL
;
8469 pTIClass
->dwHelpContext
= -1;
8470 pTIClass
->guid
= NULL
;
8471 pTIClass
->lcid
= lcid
;
8472 pTIClass
->typekind
= TKIND_COCLASS
;
8473 pTIClass
->wMajorVerNum
= 0;
8474 pTIClass
->wMinorVerNum
= 0;
8475 pTIClass
->cbAlignment
= 2;
8476 pTIClass
->cbSizeInstance
= -1;
8477 pTIClass
->cbSizeVft
= -1;
8478 pTIClass
->cFuncs
= 0;
8479 pTIClass
->cImplTypes
= 1;
8480 pTIClass
->cVars
= 0;
8481 pTIClass
->wTypeFlags
= 0;
8482 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8484 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8486 ref
= heap_alloc_zero(sizeof(*ref
));
8487 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8488 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8490 dump_TypeInfo(pTIClass
);
8492 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8494 ITypeInfo_AddRef(*pptinfo
);
8495 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8501 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8503 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8505 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8508 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8510 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8512 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8515 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8517 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8519 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8522 static HRESULT WINAPI
ITypeComp_fnBind(
8527 ITypeInfo
** ppTInfo
,
8528 DESCKIND
* pDescKind
,
8531 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8532 const TLBFuncDesc
*pFDesc
;
8533 const TLBVarDesc
*pVDesc
;
8534 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8537 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8539 *pDescKind
= DESCKIND_NONE
;
8540 pBindPtr
->lpfuncdesc
= NULL
;
8543 for(fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8544 pFDesc
= &This
->funcdescs
[fdc
];
8545 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8546 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8549 /* name found, but wrong flags */
8550 hr
= TYPE_E_TYPEMISMATCH
;
8554 if (fdc
< This
->cFuncs
)
8556 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8558 &pBindPtr
->lpfuncdesc
,
8559 This
->typekind
== TKIND_DISPATCH
);
8562 *pDescKind
= DESCKIND_FUNCDESC
;
8563 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8564 ITypeInfo_AddRef(*ppTInfo
);
8567 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, szName
);
8569 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8572 *pDescKind
= DESCKIND_VARDESC
;
8573 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8574 ITypeInfo_AddRef(*ppTInfo
);
8579 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8580 /* recursive search */
8584 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8587 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8588 ITypeInfo_Release(pTInfo
);
8592 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8593 ITypeComp_Release(pTComp
);
8594 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8595 This
->typekind
== TKIND_DISPATCH
)
8597 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8598 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8599 SysFreeString((BSTR
)tmp
);
8603 WARN("Could not search inherited interface!\n");
8605 if (hr
== DISP_E_MEMBERNOTFOUND
)
8607 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8611 static HRESULT WINAPI
ITypeComp_fnBindType(
8615 ITypeInfo
** ppTInfo
,
8616 ITypeComp
** ppTComp
)
8618 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8620 /* strange behaviour (does nothing) but like the
8623 if (!ppTInfo
|| !ppTComp
)
8632 static const ITypeCompVtbl tcompvt
=
8635 ITypeComp_fnQueryInterface
,
8637 ITypeComp_fnRelease
,
8640 ITypeComp_fnBindType
8643 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8644 ICreateTypeLib2
** ppctlib
)
8649 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8651 if (!szFile
) return E_INVALIDARG
;
8653 This
= TypeLibImpl_Constructor();
8655 return E_OUTOFMEMORY
;
8657 This
->lcid
= GetSystemDefaultLCID();
8658 This
->syskind
= syskind
;
8659 This
->ptr_size
= get_ptr_size(syskind
);
8661 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8663 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8664 return E_OUTOFMEMORY
;
8666 lstrcpyW(This
->path
, szFile
);
8668 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8669 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8673 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8674 REFIID riid
, void **object
)
8676 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8678 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8681 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8683 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8685 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8688 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8690 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8692 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8695 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8696 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8698 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8699 ITypeInfoImpl
*info
;
8702 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8704 if (!ctinfo
|| !name
)
8705 return E_INVALIDARG
;
8707 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8709 return TYPE_E_NAMECONFLICT
;
8711 if (This
->typeinfos
)
8712 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8713 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8715 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8717 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8719 info
->pTypeLib
= This
;
8720 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8721 info
->index
= This
->TypeInfoCount
;
8722 info
->typekind
= kind
;
8723 info
->cbAlignment
= 4;
8725 switch(info
->typekind
) {
8727 case TKIND_INTERFACE
:
8728 case TKIND_DISPATCH
:
8730 info
->cbSizeInstance
= This
->ptr_size
;
8734 info
->cbSizeInstance
= 0;
8737 info
->cbSizeInstance
= 2;
8740 info
->cbSizeInstance
= -0x75;
8743 FIXME("unrecognized typekind %d\n", info
->typekind
);
8744 info
->cbSizeInstance
= 0xdeadbeef;
8748 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8749 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8751 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8755 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8757 ++This
->TypeInfoCount
;
8762 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8765 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8767 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8770 return E_INVALIDARG
;
8772 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8777 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8778 WORD majorVerNum
, WORD minorVerNum
)
8780 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8782 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8784 This
->ver_major
= majorVerNum
;
8785 This
->ver_minor
= minorVerNum
;
8790 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8793 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8795 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8797 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8802 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8805 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8807 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8810 return E_INVALIDARG
;
8812 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8817 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8818 LPOLESTR helpFileName
)
8820 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8822 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8825 return E_INVALIDARG
;
8827 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8832 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8835 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8837 TRACE("%p %d\n", This
, helpContext
);
8839 This
->dwHelpContext
= helpContext
;
8844 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8847 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8849 TRACE("%p %x\n", This
, lcid
);
8851 This
->set_lcid
= lcid
;
8856 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8859 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8861 TRACE("%p %x\n", This
, libFlags
);
8863 This
->libflags
= libFlags
;
8868 typedef struct tagWMSFT_SegContents
{
8871 } WMSFT_SegContents
;
8873 typedef struct tagWMSFT_TLBFile
{
8875 WMSFT_SegContents typeinfo_seg
;
8876 WMSFT_SegContents impfile_seg
;
8877 WMSFT_SegContents impinfo_seg
;
8878 WMSFT_SegContents ref_seg
;
8879 WMSFT_SegContents guidhash_seg
;
8880 WMSFT_SegContents guid_seg
;
8881 WMSFT_SegContents namehash_seg
;
8882 WMSFT_SegContents name_seg
;
8883 WMSFT_SegContents string_seg
;
8884 WMSFT_SegContents typdesc_seg
;
8885 WMSFT_SegContents arraydesc_seg
;
8886 WMSFT_SegContents custdata_seg
;
8887 WMSFT_SegContents cdguids_seg
;
8889 WMSFT_SegContents aux_seg
;
8892 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8893 WMSFT_TLBFile
*file
)
8899 file
->string_seg
.len
= 0;
8900 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8903 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8905 return E_UNEXPECTED
;
8907 size
+= sizeof(INT16
);
8909 size
= (size
+ 4) & ~0x3;
8913 file
->string_seg
.len
+= size
;
8915 /* temporarily use str->offset to store the length of the aligned,
8916 * converted string */
8920 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8923 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8926 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8927 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8929 heap_free(file
->string_seg
.data
);
8930 return E_UNEXPECTED
;
8933 *((INT16
*)data
) = size
;
8935 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8939 str
->offset
= last_offs
;
8946 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8947 WMSFT_TLBFile
*file
)
8952 MSFT_NameIntro
*last_intro
= NULL
;
8954 file
->header
.nametablecount
= 0;
8955 file
->header
.nametablechars
= 0;
8957 file
->name_seg
.len
= 0;
8958 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8961 size
= strlenW(str
->str
);
8962 file
->header
.nametablechars
+= size
;
8963 file
->header
.nametablecount
++;
8965 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8967 return E_UNEXPECTED
;
8969 size
+= sizeof(MSFT_NameIntro
);
8971 size
= (size
+ 4) & ~0x3;
8975 file
->name_seg
.len
+= size
;
8977 /* temporarily use str->offset to store the length of the aligned,
8978 * converted string */
8982 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8983 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
8986 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8988 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8990 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8991 data
+ sizeof(MSFT_NameIntro
),
8992 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8994 heap_free(file
->name_seg
.data
);
8995 return E_UNEXPECTED
;
8997 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
8999 intro
->hreftype
= -1; /* TODO? */
9000 intro
->namelen
= size
& 0xFF;
9001 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9002 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9003 intro
->namelen
|= hash
<< 16;
9004 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9005 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9007 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9008 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9010 /* update str->offset to actual value to use in other
9011 * compilation functions that require positions within
9012 * the string table */
9016 str
->offset
= last_offs
;
9021 last_intro
->hreftype
= 0; /* last one is 0? */
9026 static inline int hash_guid(GUID
*guid
)
9030 for (i
= 0; i
< 8; i
++)
9031 hash
^= ((const short *)guid
)[i
];
9036 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9039 MSFT_GuidEntry
*entry
;
9041 int hash_key
, *guidhashtab
;
9043 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9044 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9046 entry
= file
->guid_seg
.data
;
9048 guidhashtab
= file
->guidhash_seg
.data
;
9049 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9050 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9051 entry
->hreftype
= guid
->hreftype
;
9053 hash_key
= hash_guid(&guid
->guid
);
9054 entry
->next_hash
= guidhashtab
[hash_key
];
9055 guidhashtab
[hash_key
] = offs
;
9057 guid
->offset
= offs
;
9058 offs
+= sizeof(MSFT_GuidEntry
);
9065 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9068 VARTYPE arg_type
= V_VT(value
);
9071 DWORD ret
= file
->custdata_seg
.len
;
9073 if(arg_type
== VT_INT
)
9075 if(arg_type
== VT_UINT
)
9079 if(V_VT(value
) != arg_type
) {
9080 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9082 ERR("VariantChangeType failed: %08x\n", hres
);
9087 /* Check if default value can be stored in-place */
9092 if(V_UI4(&v
) > 0x3ffffff)
9105 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9108 /* have to allocate space in custdata_seg */
9117 /* Construct the data to be allocated */
9120 if(file
->custdata_seg
.data
){
9121 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9122 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9123 file
->custdata_seg
.len
+= sizeof(int) * 2;
9125 file
->custdata_seg
.len
= sizeof(int) * 2;
9126 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9129 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9130 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9132 /* TODO: Check if the encoded data is already present in custdata_seg */
9138 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9141 if(file
->custdata_seg
.data
){
9142 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9143 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9144 file
->custdata_seg
.len
+= len
;
9146 file
->custdata_seg
.len
= len
;
9147 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9150 *((unsigned short *)data
) = V_VT(value
);
9151 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9152 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9153 if(V_BSTR(&v
)[i
] <= 0x7f)
9154 data
[i
+6] = V_BSTR(&v
)[i
];
9158 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9159 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9162 /* TODO: Check if the encoded data is already present in custdata_seg */
9167 FIXME("Argument type not yet handled\n");
9172 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9174 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9176 DWORD offs
= file
->arraydesc_seg
.len
;
9180 /* TODO: we should check for duplicates, but that's harder because each
9181 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9182 * at the library-level) */
9184 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9185 if(!file
->arraydesc_seg
.data
)
9186 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9188 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9189 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
) + offs
;
9191 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9192 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9193 for(i
= 0; i
< desc
->cDims
; ++i
){
9194 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9195 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9201 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9207 VARTYPE vt
, subtype
;
9218 vt
= desc
->vt
& VT_TYPEMASK
;
9220 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9222 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9223 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9225 *out_size
+= 2 * sizeof(DWORD
);
9226 }else if(vt
== VT_CARRAY
){
9227 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9228 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9230 }else if(vt
== VT_USERDEFINED
){
9231 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9232 encoded
[1] = desc
->u
.hreftype
;
9233 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9235 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9253 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9256 data
= file
->typdesc_seg
.data
;
9257 while(offs
< file
->typdesc_seg
.len
){
9258 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9260 offs
+= sizeof(encoded
);
9263 file
->typdesc_seg
.len
+= sizeof(encoded
);
9264 if(!file
->typdesc_seg
.data
)
9265 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9267 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9269 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9274 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9276 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9277 DWORD ret
= cdguids_seg
->len
, offs
;
9278 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
9281 if(list_empty(custdata_list
))
9284 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9285 if(!cdguids_seg
->data
){
9286 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9288 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9290 offs
= ret
+ sizeof(MSFT_CDGuid
);
9291 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9292 cdguid
->GuidOffset
= cd
->guid
->offset
;
9293 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9294 cdguid
->next
= offs
;
9295 offs
+= sizeof(MSFT_CDGuid
);
9305 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9306 WMSFT_TLBFile
*file
)
9308 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9309 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9310 MSFT_VarRecord
*varrecord
;
9311 MSFT_FuncRecord
*funcrecord
;
9313 DWORD
*name
, *offsets
, offs
;
9315 for(i
= 0; i
< info
->cFuncs
; ++i
){
9316 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9318 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9320 /* optional fields */
9321 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9322 if(!list_empty(&desc
->custdata_list
))
9323 recorded_size
+= 7 * sizeof(INT
);
9324 else if(desc
->HelpStringContext
!= 0)
9325 recorded_size
+= 6 * sizeof(INT
);
9327 else if(desc
->Entry
)
9328 recorded_size
+= 3 * sizeof(INT
);
9329 else if(desc
->HelpString
)
9330 recorded_size
+= 2 * sizeof(INT
);
9331 else if(desc
->helpcontext
)
9332 recorded_size
+= sizeof(INT
);
9334 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9336 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9337 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9338 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9343 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9346 for(i
= 0; i
< info
->cVars
; ++i
){
9347 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9349 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9351 /* optional fields */
9352 if(desc
->HelpStringContext
!= 0)
9353 recorded_size
+= 5 * sizeof(INT
);
9354 else if(!list_empty(&desc
->custdata_list
))
9355 recorded_size
+= 4 * sizeof(INT
);
9357 else if(desc
->HelpString
)
9358 recorded_size
+= 2 * sizeof(INT
);
9359 else if(desc
->HelpContext
!= 0)
9360 recorded_size
+= sizeof(INT
);
9362 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9365 if(!recorded_size
&& !extra_size
)
9368 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9370 aux_seg
->len
+= recorded_size
+ extra_size
;
9372 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9375 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9377 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9379 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9381 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9384 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9385 for(i
= 0; i
< info
->cFuncs
; ++i
){
9386 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9387 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9389 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9390 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9391 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9392 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9395 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9400 * ^has_param_defaults
9401 * ^oEntry_is_intresource
9403 funcrecord
->FKCCIC
=
9404 desc
->funcdesc
.funckind
|
9405 (desc
->funcdesc
.invkind
<< 3) |
9406 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9407 (desc
->funcdesc
.callconv
<< 8);
9409 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9410 funcrecord
->FKCCIC
|= 0x2000;
9412 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9413 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9414 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9415 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9418 if(paramdefault_size
> 0)
9419 funcrecord
->FKCCIC
|= 0x1000;
9421 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9422 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9424 /* optional fields */
9426 if(!list_empty(&desc
->custdata_list
)){
9427 size
+= 7 * sizeof(INT
);
9428 funcrecord
->HelpContext
= desc
->helpcontext
;
9429 if(desc
->HelpString
)
9430 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9432 funcrecord
->oHelpString
= -1;
9434 funcrecord
->oEntry
= -1;
9435 else if(IS_INTRESOURCE(desc
->Entry
))
9436 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9438 funcrecord
->oEntry
= desc
->Entry
->offset
;
9439 funcrecord
->res9
= -1;
9440 funcrecord
->resA
= -1;
9441 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9442 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9443 }else if(desc
->HelpStringContext
!= 0){
9444 size
+= 6 * sizeof(INT
);
9445 funcrecord
->HelpContext
= desc
->helpcontext
;
9446 if(desc
->HelpString
)
9447 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9449 funcrecord
->oHelpString
= -1;
9451 funcrecord
->oEntry
= -1;
9452 else if(IS_INTRESOURCE(desc
->Entry
))
9453 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9455 funcrecord
->oEntry
= desc
->Entry
->offset
;
9456 funcrecord
->res9
= -1;
9457 funcrecord
->resA
= -1;
9458 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9459 }else if(desc
->Entry
){
9460 size
+= 3 * sizeof(INT
);
9461 funcrecord
->HelpContext
= desc
->helpcontext
;
9462 if(desc
->HelpString
)
9463 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9465 funcrecord
->oHelpString
= -1;
9467 funcrecord
->oEntry
= -1;
9468 else if(IS_INTRESOURCE(desc
->Entry
))
9469 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9471 funcrecord
->oEntry
= desc
->Entry
->offset
;
9472 }else if(desc
->HelpString
){
9473 size
+= 2 * sizeof(INT
);
9474 funcrecord
->HelpContext
= desc
->helpcontext
;
9475 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9476 }else if(desc
->helpcontext
){
9477 size
+= sizeof(INT
);
9478 funcrecord
->HelpContext
= desc
->helpcontext
;
9481 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9482 size
+= paramdefault_size
;
9484 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9485 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9487 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9488 if(desc
->pParamDesc
[j
].Name
)
9489 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9492 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9494 if(paramdefault_size
){
9495 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9496 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9497 else if(paramdefault_size
)
9502 size
+= sizeof(MSFT_ParameterInfo
);
9505 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9511 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9514 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9515 for(i
= 0; i
< info
->cVars
; ++i
){
9516 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9517 DWORD size
= 5 * sizeof(INT
);
9519 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9520 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9521 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9522 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9524 if(desc
->vardesc
.varkind
== VAR_CONST
){
9525 varrecord
->vardescsize
+= sizeof(VARIANT
);
9526 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9528 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9531 if(desc
->HelpStringContext
!= 0){
9532 size
+= 5 * sizeof(INT
);
9533 varrecord
->HelpContext
= desc
->HelpContext
;
9534 if(desc
->HelpString
)
9535 varrecord
->HelpString
= desc
->HelpString
->offset
;
9537 varrecord
->HelpString
= -1;
9538 varrecord
->res9
= -1;
9539 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9540 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9541 }else if(!list_empty(&desc
->custdata_list
)){
9542 size
+= 4 * sizeof(INT
);
9543 varrecord
->HelpContext
= desc
->HelpContext
;
9544 if(desc
->HelpString
)
9545 varrecord
->HelpString
= desc
->HelpString
->offset
;
9547 varrecord
->HelpString
= -1;
9548 varrecord
->res9
= -1;
9549 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9550 }else if(desc
->HelpString
){
9551 size
+= 2 * sizeof(INT
);
9552 varrecord
->HelpContext
= desc
->HelpContext
;
9553 if(desc
->HelpString
)
9554 varrecord
->HelpString
= desc
->HelpString
->offset
;
9556 varrecord
->HelpString
= -1;
9557 }else if(desc
->HelpContext
!= 0){
9558 size
+= sizeof(INT
);
9559 varrecord
->HelpContext
= desc
->HelpContext
;
9562 varrecord
->Info
= size
| (i
<< 16);
9568 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9571 memid
= (MEMBERID
*)varrecord
;
9572 for(i
= 0; i
< info
->cFuncs
; ++i
){
9573 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9574 *memid
= desc
->funcdesc
.memid
;
9577 for(i
= 0; i
< info
->cVars
; ++i
){
9578 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9579 *memid
= desc
->vardesc
.memid
;
9583 name
= (UINT
*)memid
;
9584 for(i
= 0; i
< info
->cFuncs
; ++i
){
9585 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9587 *name
= desc
->Name
->offset
;
9592 for(i
= 0; i
< info
->cVars
; ++i
){
9593 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9595 *name
= desc
->Name
->offset
;
9604 typedef struct tagWMSFT_RefChunk
{
9611 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9613 DWORD offs
= file
->ref_seg
.len
, i
;
9614 WMSFT_RefChunk
*chunk
;
9616 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9617 if(!file
->ref_seg
.data
)
9618 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9620 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9622 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9624 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9625 chunk
->href
= info
->impltypes
[i
].hRef
;
9626 chunk
->res04
= info
->impltypes
[i
].implflags
;
9628 if(i
< info
->cImplTypes
- 1)
9629 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9638 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9642 size
= sizeof(MSFT_TypeInfoBase
);
9645 MSFT_TypeInfoBase
*base
= (void*)data
;
9646 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9647 base
->typekind
= TKIND_DISPATCH
;
9649 base
->typekind
= info
->typekind
;
9650 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9651 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9652 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9657 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9663 base
->posguid
= info
->guid
->offset
;
9666 base
->flags
= info
->wTypeFlags
;
9668 base
->NameOffset
= info
->Name
->offset
;
9670 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9671 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9673 base
->NameOffset
= -1;
9675 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9677 base
->docstringoffs
= info
->DocString
->offset
;
9679 base
->docstringoffs
= -1;
9680 base
->helpstringcontext
= info
->dwHelpStringContext
;
9681 base
->helpcontext
= info
->dwHelpContext
;
9682 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9683 base
->cImplTypes
= info
->cImplTypes
;
9684 base
->cbSizeVft
= info
->cbSizeVft
;
9685 base
->size
= info
->cbSizeInstance
;
9686 if(info
->typekind
== TKIND_COCLASS
){
9687 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9688 }else if(info
->typekind
== TKIND_ALIAS
){
9689 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9690 }else if(info
->typekind
== TKIND_MODULE
){
9692 base
->datatype1
= info
->DllName
->offset
;
9694 base
->datatype1
= -1;
9696 if(info
->cImplTypes
> 0)
9697 base
->datatype1
= info
->impltypes
[0].hRef
;
9699 base
->datatype1
= -1;
9701 base
->datatype2
= index
; /* FIXME: i think there's more here */
9709 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9713 file
->typeinfo_seg
.len
= 0;
9714 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9715 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9716 *junk
= file
->typeinfo_seg
.len
;
9718 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9721 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9722 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9724 file
->aux_seg
.len
= 0;
9725 file
->aux_seg
.data
= NULL
;
9727 file
->typeinfo_seg
.len
= 0;
9728 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9729 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9730 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9731 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9735 typedef struct tagWMSFT_ImpFile
{
9741 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9744 WMSFT_ImpFile
*impfile
;
9746 DWORD last_offs
= 0;
9748 file
->impfile_seg
.len
= 0;
9749 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9753 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9757 path
= implib
->name
;
9758 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9760 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9763 size
+= sizeof(INT16
);
9765 size
= (size
+ 4) & ~0x3;
9769 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9772 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9774 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9775 int strlen
= 0, size
;
9777 impfile
= (WMSFT_ImpFile
*)data
;
9778 impfile
->guid_offs
= implib
->guid
->offset
;
9779 impfile
->lcid
= implib
->lcid
;
9780 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9782 data
+= sizeof(WMSFT_ImpFile
);
9785 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9789 path
= implib
->name
;
9790 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9791 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9793 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9796 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9798 size
= strlen
+ sizeof(INT16
);
9800 size
= (size
+ 4) & ~0x3;
9803 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9806 implib
->offset
= last_offs
;
9807 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9811 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9814 TLBRefType
*ref_type
;
9817 WMSFT_compile_impfile(This
, file
);
9819 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9820 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9822 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9823 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9824 if(ref_type
->index
== TLB_REF_USE_GUID
){
9825 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9826 info
->oGuid
= ref_type
->guid
->offset
;
9828 info
->oGuid
= ref_type
->index
;
9829 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9835 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9837 file
->guidhash_seg
.len
= 0x80;
9838 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9839 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9842 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9844 file
->namehash_seg
.len
= 0x200;
9845 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9846 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9849 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9851 if(contents
&& contents
->len
){
9852 segdir
->offset
= *running_offset
;
9853 segdir
->length
= contents
->len
;
9854 *running_offset
+= segdir
->length
;
9856 segdir
->offset
= -1;
9860 /* TODO: do these ever change? */
9862 segdir
->res0c
= 0xf;
9865 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9869 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9872 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9876 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9878 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9879 base
->memoffset
+= file_len
;
9886 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9888 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9889 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9890 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9891 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9892 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9893 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9894 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9895 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9896 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9897 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9898 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9899 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9900 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9901 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9904 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9906 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9908 DWORD written
, junk_size
, junk_offs
, running_offset
;
9915 TRACE("%p\n", This
);
9917 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
9918 if(This
->typeinfos
[i
]->needs_layout
)
9919 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
9921 memset(&file
, 0, sizeof(file
));
9923 file
.header
.magic1
= 0x5446534D;
9924 file
.header
.magic2
= 0x00010002;
9925 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9926 file
.header
.lcid2
= This
->set_lcid
;
9927 file
.header
.varflags
= 0x40 | This
->syskind
;
9929 file
.header
.varflags
|= 0x10;
9930 if (This
->HelpStringDll
)
9931 file
.header
.varflags
|= HELPDLLFLAG
;
9932 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
9933 file
.header
.flags
= This
->libflags
;
9934 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9935 file
.header
.helpcontext
= This
->dwHelpContext
;
9936 file
.header
.res44
= 0x20;
9937 file
.header
.res48
= 0x80;
9938 file
.header
.dispatchpos
= This
->dispatch_href
;
9940 WMSFT_compile_namehash(This
, &file
);
9941 /* do name and string compilation to get offsets for other compilations */
9942 hres
= WMSFT_compile_names(This
, &file
);
9944 WMSFT_free_file(&file
);
9948 hres
= WMSFT_compile_strings(This
, &file
);
9950 WMSFT_free_file(&file
);
9954 WMSFT_compile_guidhash(This
, &file
);
9955 hres
= WMSFT_compile_guids(This
, &file
);
9957 WMSFT_free_file(&file
);
9962 file
.header
.helpfile
= This
->HelpFile
->offset
;
9964 file
.header
.helpfile
= -1;
9967 file
.header
.helpstring
= This
->DocString
->offset
;
9969 file
.header
.helpstring
= -1;
9971 /* do some more segment compilation */
9972 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9973 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9976 file
.header
.NameOffset
= This
->Name
->offset
;
9978 file
.header
.NameOffset
= -1;
9980 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
9983 file
.header
.posguid
= This
->guid
->offset
;
9985 file
.header
.posguid
= -1;
9987 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9988 if(file
.header
.varflags
& HELPDLLFLAG
)
9989 junk_size
+= sizeof(DWORD
);
9991 junk
= heap_alloc_zero(junk_size
);
9992 if(file
.header
.varflags
& HELPDLLFLAG
){
9993 *junk
= This
->HelpStringDll
->offset
;
10002 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10003 WMSFT_compile_impinfo(This
, &file
);
10005 running_offset
= 0;
10007 TRACE("header at: 0x%x\n", running_offset
);
10008 running_offset
+= sizeof(file
.header
);
10010 TRACE("junk at: 0x%x\n", running_offset
);
10011 running_offset
+= junk_size
;
10013 TRACE("segdir at: 0x%x\n", running_offset
);
10014 running_offset
+= sizeof(file
.segdir
);
10016 TRACE("typeinfo at: 0x%x\n", running_offset
);
10017 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10019 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10020 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10022 TRACE("guidtab at: 0x%x\n", running_offset
);
10023 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10025 TRACE("reftab at: 0x%x\n", running_offset
);
10026 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10028 TRACE("impinfo at: 0x%x\n", running_offset
);
10029 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10031 TRACE("impfiles at: 0x%x\n", running_offset
);
10032 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10034 TRACE("namehashtab at: 0x%x\n", running_offset
);
10035 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10037 TRACE("nametab at: 0x%x\n", running_offset
);
10038 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10040 TRACE("stringtab at: 0x%x\n", running_offset
);
10041 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10043 TRACE("typdesc at: 0x%x\n", running_offset
);
10044 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10046 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10047 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10049 TRACE("custdata at: 0x%x\n", running_offset
);
10050 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10052 TRACE("cdguids at: 0x%x\n", running_offset
);
10053 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10055 TRACE("res0e at: 0x%x\n", running_offset
);
10056 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10058 TRACE("res0f at: 0x%x\n", running_offset
);
10059 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10061 TRACE("aux_seg at: 0x%x\n", running_offset
);
10063 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10065 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10066 FILE_ATTRIBUTE_NORMAL
, 0);
10067 if (outfile
== INVALID_HANDLE_VALUE
){
10068 WMSFT_free_file(&file
);
10070 return TYPE_E_IOERROR
;
10073 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10075 WMSFT_free_file(&file
);
10076 CloseHandle(outfile
);
10078 return TYPE_E_IOERROR
;
10081 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10084 WMSFT_free_file(&file
);
10085 CloseHandle(outfile
);
10086 return TYPE_E_IOERROR
;
10089 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10091 WMSFT_free_file(&file
);
10092 CloseHandle(outfile
);
10093 return TYPE_E_IOERROR
;
10096 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10097 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10098 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10099 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10100 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10101 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10102 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10103 WMSFT_write_segment(outfile
, &file
.name_seg
);
10104 WMSFT_write_segment(outfile
, &file
.string_seg
);
10105 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10106 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10107 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10108 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10109 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10111 WMSFT_free_file(&file
);
10113 CloseHandle(outfile
);
10118 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10121 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10122 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10126 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10127 REFGUID guid
, VARIANT
*varVal
)
10129 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10130 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
10134 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10135 ULONG helpStringContext
)
10137 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10138 FIXME("%p %u - stub\n", This
, helpStringContext
);
10142 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10145 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10146 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10149 return E_INVALIDARG
;
10151 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10156 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10157 ICreateTypeLib2_fnQueryInterface
,
10158 ICreateTypeLib2_fnAddRef
,
10159 ICreateTypeLib2_fnRelease
,
10160 ICreateTypeLib2_fnCreateTypeInfo
,
10161 ICreateTypeLib2_fnSetName
,
10162 ICreateTypeLib2_fnSetVersion
,
10163 ICreateTypeLib2_fnSetGuid
,
10164 ICreateTypeLib2_fnSetDocString
,
10165 ICreateTypeLib2_fnSetHelpFileName
,
10166 ICreateTypeLib2_fnSetHelpContext
,
10167 ICreateTypeLib2_fnSetLcid
,
10168 ICreateTypeLib2_fnSetLibFlags
,
10169 ICreateTypeLib2_fnSaveAllChanges
,
10170 ICreateTypeLib2_fnDeleteTypeInfo
,
10171 ICreateTypeLib2_fnSetCustData
,
10172 ICreateTypeLib2_fnSetHelpStringContext
,
10173 ICreateTypeLib2_fnSetHelpStringDll
10176 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10177 REFIID riid
, void **object
)
10179 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10181 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10184 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10186 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10188 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10191 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10193 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10195 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10198 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10201 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10203 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10205 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10210 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10213 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10217 TRACE("%p %x\n", This
, typeFlags
);
10219 if (typeFlags
& TYPEFLAG_FDUAL
) {
10220 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10222 ITypeInfo
*dispatch
;
10226 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10230 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10231 ITypeLib_Release(stdole
);
10235 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10236 ITypeInfo_Release(dispatch
);
10241 old_flags
= This
->wTypeFlags
;
10242 This
->wTypeFlags
= typeFlags
;
10244 hres
= ICreateTypeInfo2_LayOut(iface
);
10245 if (FAILED(hres
)) {
10246 This
->wTypeFlags
= old_flags
;
10253 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10256 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10258 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10261 return E_INVALIDARG
;
10263 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10268 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10271 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10273 TRACE("%p %d\n", This
, helpContext
);
10275 This
->dwHelpContext
= helpContext
;
10280 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10281 WORD majorVerNum
, WORD minorVerNum
)
10283 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10285 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10287 This
->wMajorVerNum
= majorVerNum
;
10288 This
->wMinorVerNum
= minorVerNum
;
10293 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10294 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10296 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10298 ITypeLib
*container
;
10299 TLBRefType
*ref_type
;
10301 TYPEATTR
*typeattr
;
10305 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10307 if (!typeInfo
|| !refType
)
10308 return E_INVALIDARG
;
10310 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10314 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10315 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10317 ITypeLib_Release(container
);
10319 *refType
= target
->hreftype
;
10324 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10325 if (FAILED(hres
)) {
10326 ITypeLib_Release(container
);
10330 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10331 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10332 implib
->lcid
== libattr
->lcid
&&
10333 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10334 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10338 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10339 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10341 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10342 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10343 implib
->name
= SysAllocString(our_container
->path
);
10345 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10346 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10348 implib
->name
= NULL
;
10349 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10353 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10354 implib
->lcid
= libattr
->lcid
;
10355 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10356 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10358 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10361 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10362 ITypeLib_Release(container
);
10364 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10369 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10370 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10371 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10372 ref_type
->tkind
== typeattr
->typekind
)
10377 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10378 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10380 ref_type
->tkind
= typeattr
->typekind
;
10381 ref_type
->pImpTLInfo
= implib
;
10382 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10384 ref_type
->index
= TLB_REF_USE_GUID
;
10386 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10388 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10391 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10393 *refType
= ref_type
->reference
| 0x1;
10395 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10396 This
->pTypeLib
->dispatch_href
= *refType
;
10401 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10402 UINT index
, FUNCDESC
*funcDesc
)
10404 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10405 TLBFuncDesc tmp_func_desc
, *func_desc
;
10410 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10412 if (!funcDesc
|| funcDesc
->oVft
& 3)
10413 return E_INVALIDARG
;
10415 switch (This
->typekind
) {
10417 if (funcDesc
->funckind
!= FUNC_STATIC
)
10418 return TYPE_E_BADMODULEKIND
;
10420 case TKIND_DISPATCH
:
10421 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10422 return TYPE_E_BADMODULEKIND
;
10425 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10426 return TYPE_E_BADMODULEKIND
;
10429 if (index
> This
->cFuncs
)
10430 return TYPE_E_ELEMENTNOTFOUND
;
10432 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10433 !funcDesc
->cParams
)
10434 return TYPE_E_INCONSISTENTPROPFUNCS
;
10437 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10438 funcDesc
->oVft
% 8 != 0)
10439 return E_INVALIDARG
;
10442 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10443 TLBFuncDesc_Constructor(&tmp_func_desc
);
10445 tmp_func_desc
.funcdesc
= *funcDesc
;
10447 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10448 tmp_func_desc
.funcdesc
.oVft
|= 1;
10450 if (funcDesc
->cScodes
) {
10451 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10452 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10454 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10456 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10457 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10458 buf_size
+= sizeof(ELEMDESC
);
10459 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10461 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10462 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10464 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10465 if (FAILED(hres
)) {
10466 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10467 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10471 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10472 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10473 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10474 if (FAILED(hres
)) {
10475 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10476 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10479 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10480 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10481 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10482 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10483 if (FAILED(hres
)) {
10484 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10485 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10491 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10493 if (This
->funcdescs
) {
10494 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10495 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10497 if (index
< This
->cFuncs
) {
10498 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10499 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10500 func_desc
= This
->funcdescs
+ index
;
10502 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10504 /* move custdata lists to the new memory location */
10505 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10507 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10508 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10509 list_init(&fd
->custdata_list
);
10511 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10512 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10517 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10519 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10520 list_init(&func_desc
->custdata_list
);
10524 This
->needs_layout
= TRUE
;
10529 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10530 UINT index
, HREFTYPE refType
)
10532 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10533 TLBImplType
*impl_type
;
10536 TRACE("%p %u %d\n", This
, index
, refType
);
10538 switch(This
->typekind
){
10539 case TKIND_COCLASS
: {
10541 FIXME("Unhandled index: -1\n");
10545 if(index
!= This
->cImplTypes
)
10546 return TYPE_E_ELEMENTNOTFOUND
;
10550 case TKIND_INTERFACE
:
10551 case TKIND_DISPATCH
:
10552 if (index
!= 0 || This
->cImplTypes
)
10553 return TYPE_E_ELEMENTNOTFOUND
;
10556 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10560 if (This
->impltypes
){
10563 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10564 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10566 if (index
< This
->cImplTypes
) {
10567 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10568 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10569 impl_type
= This
->impltypes
+ index
;
10571 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10573 /* move custdata lists to the new memory location */
10574 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10576 TLBImplType
*it
= &This
->impltypes
[i
];
10577 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10578 list_init(&it
->custdata_list
);
10580 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10581 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10586 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10588 memset(impl_type
, 0, sizeof(TLBImplType
));
10589 TLBImplType_Constructor(impl_type
);
10590 impl_type
->hRef
= refType
;
10592 ++This
->cImplTypes
;
10594 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10595 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10597 hres
= ICreateTypeInfo2_LayOut(iface
);
10604 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10605 UINT index
, INT implTypeFlags
)
10607 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10608 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10610 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10612 if (This
->typekind
!= TKIND_COCLASS
)
10613 return TYPE_E_BADMODULEKIND
;
10615 if (index
>= This
->cImplTypes
)
10616 return TYPE_E_ELEMENTNOTFOUND
;
10618 impl_type
->implflags
= implTypeFlags
;
10623 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10626 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10628 TRACE("%p %d\n", This
, alignment
);
10630 This
->cbAlignment
= alignment
;
10635 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10638 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10640 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10643 return E_INVALIDARG
;
10645 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10647 This
->lpstrSchema
= This
->Schema
->str
;
10652 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10653 UINT index
, VARDESC
*varDesc
)
10655 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10656 TLBVarDesc
*var_desc
;
10658 TRACE("%p %u %p\n", This
, index
, varDesc
);
10660 if (This
->vardescs
){
10663 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10664 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10666 if (index
< This
->cVars
) {
10667 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10668 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10669 var_desc
= This
->vardescs
+ index
;
10671 var_desc
= This
->vardescs
+ This
->cVars
;
10673 /* move custdata lists to the new memory location */
10674 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10676 TLBVarDesc
*var
= &This
->vardescs
[i
];
10677 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10678 list_init(&var
->custdata_list
);
10680 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10681 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10686 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10688 TLBVarDesc_Constructor(var_desc
);
10689 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10690 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10694 This
->needs_layout
= TRUE
;
10699 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10700 UINT index
, LPOLESTR
*names
, UINT numNames
)
10702 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10703 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10706 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10709 return E_INVALIDARG
;
10711 if (index
>= This
->cFuncs
|| numNames
== 0)
10712 return TYPE_E_ELEMENTNOTFOUND
;
10714 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10715 if(numNames
> func_desc
->funcdesc
.cParams
)
10716 return TYPE_E_ELEMENTNOTFOUND
;
10718 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10719 return TYPE_E_ELEMENTNOTFOUND
;
10721 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10722 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10723 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10724 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10725 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10726 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10728 return TYPE_E_AMBIGUOUSNAME
;
10732 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10734 for (i
= 1; i
< numNames
; ++i
) {
10735 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10736 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10742 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10743 UINT index
, LPOLESTR name
)
10745 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10747 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10750 return E_INVALIDARG
;
10752 if(index
>= This
->cVars
)
10753 return TYPE_E_ELEMENTNOTFOUND
;
10755 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10759 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10760 TYPEDESC
*tdescAlias
)
10762 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10765 TRACE("%p %p\n", This
, tdescAlias
);
10768 return E_INVALIDARG
;
10770 if(This
->typekind
!= TKIND_ALIAS
)
10771 return TYPE_E_BADMODULEKIND
;
10773 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->cbSizeInstance
, &This
->cbAlignment
);
10777 heap_free(This
->tdescAlias
);
10778 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10779 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10784 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10785 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10787 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10788 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10792 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10793 UINT index
, LPOLESTR docString
)
10795 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10796 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10798 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10801 return E_INVALIDARG
;
10803 if(index
>= This
->cFuncs
)
10804 return TYPE_E_ELEMENTNOTFOUND
;
10806 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10811 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10812 UINT index
, LPOLESTR docString
)
10814 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10815 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10817 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10820 return E_INVALIDARG
;
10822 if(index
>= This
->cVars
)
10823 return TYPE_E_ELEMENTNOTFOUND
;
10825 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10830 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10831 UINT index
, DWORD helpContext
)
10833 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10834 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10836 TRACE("%p %u %d\n", This
, index
, helpContext
);
10838 if(index
>= This
->cFuncs
)
10839 return TYPE_E_ELEMENTNOTFOUND
;
10841 func_desc
->helpcontext
= helpContext
;
10846 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10847 UINT index
, DWORD helpContext
)
10849 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10850 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10852 TRACE("%p %u %d\n", This
, index
, helpContext
);
10854 if(index
>= This
->cVars
)
10855 return TYPE_E_ELEMENTNOTFOUND
;
10857 var_desc
->HelpContext
= helpContext
;
10862 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10863 UINT index
, BSTR bstrMops
)
10865 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10866 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10870 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10873 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10875 TRACE("%p %p\n", This
, idlDesc
);
10878 return E_INVALIDARG
;
10880 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10881 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10886 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10888 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10890 TLBFuncDesc
*func_desc
;
10891 UINT user_vft
= 0, i
, depth
= 0;
10892 HRESULT hres
= S_OK
;
10894 TRACE("%p\n", This
);
10896 This
->needs_layout
= FALSE
;
10898 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10902 if (This
->typekind
== TKIND_INTERFACE
) {
10907 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10909 if (SUCCEEDED(hres
)) {
10910 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10912 if (SUCCEEDED(hres
)) {
10913 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10914 if (FAILED(hres
)) {
10915 ITypeInfo_Release(inh
);
10916 ITypeInfo_Release(tinfo
);
10919 This
->cbSizeVft
= attr
->cbSizeVft
;
10920 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10924 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10925 if(SUCCEEDED(hres
)){
10927 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10928 if(SUCCEEDED(hres
)){
10929 ITypeInfo_Release(inh
);
10933 }while(SUCCEEDED(hres
));
10936 ITypeInfo_Release(inh
);
10937 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10938 This
->cbSizeVft
= 0;
10941 ITypeInfo_Release(tinfo
);
10944 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10945 This
->cbSizeVft
= 0;
10948 ITypeInfo_Release(tinfo
);
10951 } else if (This
->typekind
== TKIND_DISPATCH
)
10952 This
->cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10954 This
->cbSizeVft
= 0;
10956 func_desc
= This
->funcdescs
;
10958 while (i
< This
->cFuncs
) {
10959 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10960 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
10962 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10963 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10965 This
->cbSizeVft
+= This
->pTypeLib
->ptr_size
;
10967 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10970 BOOL reset
= FALSE
;
10972 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10974 iter
= This
->funcdescs
;
10975 while (j
< This
->cFuncs
) {
10976 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10978 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
10981 ++func_desc
->funcdesc
.memid
;
10982 iter
= This
->funcdescs
;
10995 if (user_vft
> This
->cbSizeVft
)
10996 This
->cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
10998 for(i
= 0; i
< This
->cVars
; ++i
){
10999 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11000 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11002 BOOL reset
= FALSE
;
11005 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11007 iter
= This
->vardescs
;
11008 while (j
< This
->cVars
) {
11009 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11011 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->cVars
;
11014 ++var_desc
->vardesc
.memid
;
11015 iter
= This
->vardescs
;
11025 ITypeInfo_Release(tinfo
);
11029 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11032 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11033 FIXME("%p %u - stub\n", This
, index
);
11037 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11038 MEMBERID memid
, INVOKEKIND invKind
)
11040 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11041 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11045 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11048 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11049 FIXME("%p %u - stub\n", This
, index
);
11053 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11056 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11057 FIXME("%p %x - stub\n", This
, memid
);
11061 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11064 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11065 FIXME("%p %u - stub\n", This
, index
);
11069 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11070 REFGUID guid
, VARIANT
*varVal
)
11074 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11076 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11078 if (!guid
|| !varVal
)
11079 return E_INVALIDARG
;
11081 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11083 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11086 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11087 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11089 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11090 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11094 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11095 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11097 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11098 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11102 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11103 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11105 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11106 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11110 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11111 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11113 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11114 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11118 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11119 ULONG helpStringContext
)
11121 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11123 TRACE("%p %u\n", This
, helpStringContext
);
11125 This
->dwHelpStringContext
= helpStringContext
;
11130 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11131 UINT index
, ULONG helpStringContext
)
11133 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11134 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11138 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11139 UINT index
, ULONG helpStringContext
)
11141 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11142 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11146 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11148 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11149 FIXME("%p - stub\n", This
);
11153 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11156 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11158 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11161 return E_INVALIDARG
;
11163 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11168 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11169 ICreateTypeInfo2_fnQueryInterface
,
11170 ICreateTypeInfo2_fnAddRef
,
11171 ICreateTypeInfo2_fnRelease
,
11172 ICreateTypeInfo2_fnSetGuid
,
11173 ICreateTypeInfo2_fnSetTypeFlags
,
11174 ICreateTypeInfo2_fnSetDocString
,
11175 ICreateTypeInfo2_fnSetHelpContext
,
11176 ICreateTypeInfo2_fnSetVersion
,
11177 ICreateTypeInfo2_fnAddRefTypeInfo
,
11178 ICreateTypeInfo2_fnAddFuncDesc
,
11179 ICreateTypeInfo2_fnAddImplType
,
11180 ICreateTypeInfo2_fnSetImplTypeFlags
,
11181 ICreateTypeInfo2_fnSetAlignment
,
11182 ICreateTypeInfo2_fnSetSchema
,
11183 ICreateTypeInfo2_fnAddVarDesc
,
11184 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11185 ICreateTypeInfo2_fnSetVarName
,
11186 ICreateTypeInfo2_fnSetTypeDescAlias
,
11187 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11188 ICreateTypeInfo2_fnSetFuncDocString
,
11189 ICreateTypeInfo2_fnSetVarDocString
,
11190 ICreateTypeInfo2_fnSetFuncHelpContext
,
11191 ICreateTypeInfo2_fnSetVarHelpContext
,
11192 ICreateTypeInfo2_fnSetMops
,
11193 ICreateTypeInfo2_fnSetTypeIdldesc
,
11194 ICreateTypeInfo2_fnLayOut
,
11195 ICreateTypeInfo2_fnDeleteFuncDesc
,
11196 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11197 ICreateTypeInfo2_fnDeleteVarDesc
,
11198 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11199 ICreateTypeInfo2_fnDeleteImplType
,
11200 ICreateTypeInfo2_fnSetCustData
,
11201 ICreateTypeInfo2_fnSetFuncCustData
,
11202 ICreateTypeInfo2_fnSetParamCustData
,
11203 ICreateTypeInfo2_fnSetVarCustData
,
11204 ICreateTypeInfo2_fnSetImplTypeCustData
,
11205 ICreateTypeInfo2_fnSetHelpStringContext
,
11206 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11207 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11208 ICreateTypeInfo2_fnInvalidate
,
11209 ICreateTypeInfo2_fnSetName
11212 /******************************************************************************
11213 * ClearCustData (OLEAUT32.171)
11215 * Clear a custom data type's data.
11218 * lpCust [I] The custom data type instance
11223 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11225 if (lpCust
&& lpCust
->cCustData
)
11227 if (lpCust
->prgCustData
)
11231 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11232 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11234 /* FIXME - Should be using a per-thread IMalloc */
11235 heap_free(lpCust
->prgCustData
);
11236 lpCust
->prgCustData
= NULL
;
11238 lpCust
->cCustData
= 0;