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 FALSE
;
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_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3409 if(h
!= INVALID_HANDLE_VALUE
){
3410 FILE_NAME_INFORMATION
*info
;
3411 char data
[MAX_PATH
* sizeof(WCHAR
) + sizeof(info
->FileNameLength
)];
3414 info
= (FILE_NAME_INFORMATION
*)data
;
3415 /* GetFileInformationByHandleEx returns the path of the file without
3416 * WOW64 redirection */
3417 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, data
, sizeof(data
));
3419 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3420 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3425 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3427 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3428 EnterCriticalSection(&cache_section
);
3429 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3431 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3433 TRACE("cache hit\n");
3434 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3435 ITypeLib2_AddRef(*ppTypeLib
);
3436 LeaveCriticalSection(&cache_section
);
3440 LeaveCriticalSection(&cache_section
);
3442 /* now actually load and parse the typelib */
3444 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3445 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3446 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3447 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3448 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3451 if (dwTLBLength
>= 4)
3453 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3454 if (dwSignature
== MSFT_SIGNATURE
)
3455 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3456 else if (dwSignature
== SLTG_SIGNATURE
)
3457 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3460 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3461 ret
= TYPE_E_CANTLOADLIBRARY
;
3465 ret
= TYPE_E_CANTLOADLIBRARY
;
3466 IUnknown_Release(pFile
);
3470 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3472 TRACE("adding to cache\n");
3473 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3474 lstrcpyW(impl
->path
, pszPath
);
3475 /* We should really canonicalise the path here. */
3476 impl
->index
= index
;
3478 /* FIXME: check if it has added already in the meantime */
3479 EnterCriticalSection(&cache_section
);
3480 list_add_head(&tlb_cache
, &impl
->entry
);
3481 LeaveCriticalSection(&cache_section
);
3487 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3489 ret
= TYPE_E_CANTLOADLIBRARY
;
3496 /*================== ITypeLib(2) Methods ===================================*/
3498 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3500 ITypeLibImpl
* pTypeLibImpl
;
3502 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3503 if (!pTypeLibImpl
) return NULL
;
3505 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3506 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3507 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3508 pTypeLibImpl
->ref
= 1;
3510 list_init(&pTypeLibImpl
->implib_list
);
3511 list_init(&pTypeLibImpl
->custdata_list
);
3512 list_init(&pTypeLibImpl
->name_list
);
3513 list_init(&pTypeLibImpl
->string_list
);
3514 list_init(&pTypeLibImpl
->guid_list
);
3515 list_init(&pTypeLibImpl
->ref_list
);
3516 pTypeLibImpl
->dispatch_href
= -1;
3518 return pTypeLibImpl
;
3521 /****************************************************************************
3522 * ITypeLib2_Constructor_MSFT
3524 * loading an MSFT typelib from an in-memory image
3526 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3530 MSFT_Header tlbHeader
;
3531 MSFT_SegDir tlbSegDir
;
3532 ITypeLibImpl
* pTypeLibImpl
;
3535 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3537 pTypeLibImpl
= TypeLibImpl_Constructor();
3538 if (!pTypeLibImpl
) return NULL
;
3540 /* get pointer to beginning of typelib data */
3544 cx
.pLibInfo
= pTypeLibImpl
;
3545 cx
.length
= dwTLBLength
;
3548 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3549 TRACE_(typelib
)("header:\n");
3550 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3551 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3552 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3555 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3557 /* there is a small amount of information here until the next important
3559 * the segment directory . Try to calculate the amount of data */
3560 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3562 /* now read the segment directory */
3563 TRACE("read segment directory (at %d)\n",lPSegDir
);
3564 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3565 cx
.pTblDir
= &tlbSegDir
;
3567 /* just check two entries */
3568 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3570 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3571 heap_free(pTypeLibImpl
);
3575 MSFT_ReadAllNames(&cx
);
3576 MSFT_ReadAllStrings(&cx
);
3577 MSFT_ReadAllGuids(&cx
);
3579 /* now fill our internal data */
3580 /* TLIBATTR fields */
3581 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3583 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3584 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3585 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3586 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3587 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3589 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3590 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3592 /* name, eventually add to a hash table */
3593 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3596 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3597 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3599 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3602 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3603 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3606 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3609 if(tlbHeader
.CustomDataOffset
>= 0)
3611 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3614 /* fill in type descriptions */
3615 if(tlbSegDir
.pTypdescTab
.length
> 0)
3617 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3619 pTypeLibImpl
->ctTypeDesc
= cTD
;
3620 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3621 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3624 /* FIXME: add several sanity checks here */
3625 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3626 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3628 /* FIXME: check safearray */
3630 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3632 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3634 else if(td
[0] == VT_CARRAY
)
3636 /* array descr table here */
3637 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3639 else if(td
[0] == VT_USERDEFINED
)
3641 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3643 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3646 /* second time around to fill the array subscript info */
3649 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3650 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3652 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3653 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3656 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3658 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3660 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3662 for(j
= 0; j
<td
[2]; j
++)
3664 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3665 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3666 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3667 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3672 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3673 ERR("didn't find array description data\n");
3678 /* imported type libs */
3679 if(tlbSegDir
.pImpFiles
.offset
>0)
3682 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3685 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3689 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3690 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3691 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3693 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3694 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3695 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3696 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3699 name
= heap_alloc_zero(size
+1);
3700 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3701 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3704 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3705 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3707 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3711 MSFT_ReadAllRefs(&cx
);
3713 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3716 if(tlbHeader
.nrtypeinfos
>= 0 )
3718 ITypeInfoImpl
**ppTI
;
3720 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3722 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3724 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3727 (pTypeLibImpl
->TypeInfoCount
)++;
3732 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3733 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3734 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3738 TRACE("(%p)\n", pTypeLibImpl
);
3739 return &pTypeLibImpl
->ITypeLib2_iface
;
3743 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3749 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3750 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3754 guid
->Data4
[0] = s
>> 8;
3755 guid
->Data4
[1] = s
& 0xff;
3758 for(i
= 0; i
< 6; i
++) {
3759 memcpy(b
, str
+ 24 + 2 * i
, 2);
3760 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3765 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3772 bytelen
= *(const WORD
*)ptr
;
3773 if(bytelen
== 0xffff) return 2;
3775 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3776 tmp_str
= SysAllocStringLen(NULL
, len
);
3778 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3779 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3780 SysFreeString(tmp_str
);
3785 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3790 bytelen
= *(const WORD
*)ptr
;
3791 if(bytelen
== 0xffff) return 2;
3792 *str
= heap_alloc(bytelen
+ 1);
3793 memcpy(*str
, ptr
+ 2, bytelen
);
3794 (*str
)[bytelen
] = '\0';
3798 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3803 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3804 if (tlbstr
->offset
== offset
)
3808 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3809 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3810 SysFreeString(tmp_str
);
3815 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3817 char *ptr
= pLibBlk
;
3820 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3821 FIXME("libblk magic = %04x\n", w
);
3826 if((w
= *(WORD
*)ptr
) != 0xffff) {
3827 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3832 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3834 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3836 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3839 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3840 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3843 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3844 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3846 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3849 ptr
+= 4; /* skip res12 */
3851 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3854 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3857 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3860 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3861 ptr
+= sizeof(GUID
);
3863 return ptr
- (char*)pLibBlk
;
3866 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3871 } sltg_ref_lookup_t
;
3873 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3874 HREFTYPE
*typelib_ref
)
3876 if(table
&& typeinfo_ref
< table
->num
)
3878 *typelib_ref
= table
->refs
[typeinfo_ref
];
3882 ERR_(typelib
)("Unable to find reference\n");
3887 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3892 if((*pType
& 0xe00) == 0xe00) {
3894 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3895 pTD
= pTD
->u
.lptdesc
;
3897 switch(*pType
& 0x3f) {
3900 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3901 pTD
= pTD
->u
.lptdesc
;
3904 case VT_USERDEFINED
:
3905 pTD
->vt
= VT_USERDEFINED
;
3906 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3912 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3915 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3917 pTD
->vt
= VT_CARRAY
;
3918 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3919 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3920 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3921 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3923 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3929 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3933 pTD
->vt
= VT_SAFEARRAY
;
3934 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3935 pTD
= pTD
->u
.lptdesc
;
3939 pTD
->vt
= *pType
& 0x3f;
3948 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3949 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3951 /* Handle [in/out] first */
3952 if((*pType
& 0xc000) == 0xc000)
3953 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3954 else if(*pType
& 0x8000)
3955 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3956 else if(*pType
& 0x4000)
3957 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3959 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3962 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3965 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3967 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3971 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3976 TLBRefType
*ref_type
;
3977 sltg_ref_lookup_t
*table
;
3978 HREFTYPE typelib_ref
;
3980 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3981 FIXME("Ref magic = %x\n", pRef
->magic
);
3984 name
= ( (char*)pRef
->names
+ pRef
->number
);
3986 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3987 table
->num
= pRef
->number
>> 3;
3989 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3991 /* We don't want the first href to be 0 */
3992 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3994 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3996 unsigned int lib_offs
, type_num
;
3998 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
4000 name
+= SLTG_ReadStringA(name
, &refname
);
4001 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
4002 FIXME_(typelib
)("Can't sscanf ref\n");
4003 if(lib_offs
!= 0xffff) {
4006 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
4007 if(import
->offset
== lib_offs
)
4010 if(&import
->entry
== &pTL
->implib_list
) {
4011 char fname
[MAX_PATH
+1];
4015 import
= heap_alloc_zero(sizeof(*import
));
4016 import
->offset
= lib_offs
;
4017 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
4018 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
4019 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
4020 &import
->wVersionMajor
,
4021 &import
->wVersionMinor
,
4022 &import
->lcid
, fname
) != 4) {
4023 FIXME_(typelib
)("can't sscanf ref %s\n",
4024 pNameTable
+ lib_offs
+ 40);
4026 len
= strlen(fname
);
4027 if(fname
[len
-1] != '#')
4028 FIXME("fname = %s\n", fname
);
4029 fname
[len
-1] = '\0';
4030 import
->name
= TLB_MultiByteToBSTR(fname
);
4031 list_add_tail(&pTL
->implib_list
, &import
->entry
);
4033 ref_type
->pImpTLInfo
= import
;
4035 /* Store a reference to IDispatch */
4036 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
4037 pTL
->dispatch_href
= typelib_ref
;
4039 } else { /* internal ref */
4040 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
4042 ref_type
->reference
= typelib_ref
;
4043 ref_type
->index
= type_num
;
4046 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
4048 table
->refs
[ref
] = typelib_ref
;
4051 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
4052 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
4053 dump_TLBRefType(pTL
);
4057 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
4058 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
4060 SLTG_ImplInfo
*info
;
4061 TLBImplType
*pImplType
;
4062 /* I don't really get this structure, usually it's 0x16 bytes
4063 long, but iuser.tlb contains some that are 0x18 bytes long.
4064 That's ok because we can use the next ptr to jump to the next
4065 one. But how do we know the length of the last one? The WORD
4066 at offs 0x8 might be the clue. For now I'm just assuming that
4067 the last one is the regular 0x16 bytes. */
4069 info
= (SLTG_ImplInfo
*)pBlk
;
4072 if(info
->next
== 0xffff)
4074 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4077 info
= (SLTG_ImplInfo
*)pBlk
;
4078 pTI
->impltypes
= TLBImplType_Alloc(pTI
->cImplTypes
);
4079 pImplType
= pTI
->impltypes
;
4081 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4082 pImplType
->implflags
= info
->impltypeflags
;
4085 if(info
->next
== 0xffff)
4088 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4089 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4091 info
++; /* see comment at top of function */
4095 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4096 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4098 TLBVarDesc
*pVarDesc
;
4099 const TLBString
*prevName
= NULL
;
4100 SLTG_Variable
*pItem
;
4104 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4106 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4107 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4109 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4111 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4112 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4113 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4117 if (pItem
->name
== 0xfffe)
4118 pVarDesc
->Name
= prevName
;
4120 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4122 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4123 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4124 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4126 if(pItem
->flags
& 0x02)
4127 pType
= &pItem
->type
;
4129 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4131 if (pItem
->flags
& ~0xda)
4132 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4134 SLTG_DoElem(pType
, pBlk
,
4135 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4137 if (TRACE_ON(typelib
)) {
4139 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4140 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4143 if (pItem
->flags
& 0x40) {
4144 TRACE_(typelib
)("VAR_DISPATCH\n");
4145 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4147 else if (pItem
->flags
& 0x10) {
4148 TRACE_(typelib
)("VAR_CONST\n");
4149 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4150 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4151 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4152 if (pItem
->flags
& 0x08)
4153 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4155 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4161 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4163 TRACE_(typelib
)("len = %u\n", len
);
4164 if (len
== 0xffff) {
4167 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4168 str
= SysAllocStringLen(NULL
, alloc_len
);
4169 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4171 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4172 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4181 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4182 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4185 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4190 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4191 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4192 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4195 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4196 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4198 if (pItem
->flags
& 0x80)
4199 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4201 prevName
= pVarDesc
->Name
;
4206 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4207 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4209 SLTG_Function
*pFunc
;
4211 TLBFuncDesc
*pFuncDesc
;
4213 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4215 pFuncDesc
= pTI
->funcdescs
;
4216 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4217 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4222 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4223 case SLTG_FUNCTION_MAGIC
:
4224 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4226 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4227 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4229 case SLTG_STATIC_FUNCTION_MAGIC
:
4230 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4233 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4236 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4238 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4239 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4240 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4241 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4242 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4243 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4245 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4246 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4248 if(pFunc
->retnextopt
& 0x80)
4249 pType
= &pFunc
->rettype
;
4251 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4253 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4255 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4256 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4257 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4259 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4261 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4262 char *paramName
= pNameTable
+ *pArg
;
4264 /* If arg type follows then paramName points to the 2nd
4265 letter of the name, else the next WORD is an offset to
4266 the arg type and paramName points to the first letter.
4267 So let's take one char off paramName and see if we're
4268 pointing at an alpha-numeric char. However if *pArg is
4269 0xffff or 0xfffe then the param has no name, the former
4270 meaning that the next WORD is the type, the latter
4271 meaning that the next WORD is an offset to the type. */
4276 else if(*pArg
== 0xfffe) {
4280 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4285 if(HaveOffs
) { /* the next word is an offset to type */
4286 pType
= (WORD
*)(pBlk
+ *pArg
);
4287 SLTG_DoElem(pType
, pBlk
,
4288 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4293 pArg
= SLTG_DoElem(pArg
, pBlk
,
4294 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4297 /* Are we an optional param ? */
4298 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4299 pFuncDesc
->funcdesc
.cParamsOpt
)
4300 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4303 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4304 paramName
- pNameTable
, pTI
->pTypeLib
);
4306 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4310 pTI
->cFuncs
= cFuncs
;
4313 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4314 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4315 SLTG_TypeInfoTail
*pTITail
)
4318 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4320 if(pTIHeader
->href_table
!= 0xffffffff) {
4321 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4327 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4328 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4330 heap_free(ref_lookup
);
4334 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4335 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4336 const SLTG_TypeInfoTail
*pTITail
)
4339 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4341 if(pTIHeader
->href_table
!= 0xffffffff) {
4342 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4348 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4349 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4352 if (pTITail
->funcs_off
!= 0xffff)
4353 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4355 heap_free(ref_lookup
);
4357 if (TRACE_ON(typelib
))
4358 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4361 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4362 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4363 const SLTG_TypeInfoTail
*pTITail
)
4365 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4368 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4369 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4370 const SLTG_TypeInfoTail
*pTITail
)
4373 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4375 if (pTITail
->simple_alias
) {
4376 /* if simple alias, no more processing required */
4377 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4378 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4382 if(pTIHeader
->href_table
!= 0xffffffff) {
4383 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4387 /* otherwise it is an offset to a type */
4388 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4390 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4391 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4393 heap_free(ref_lookup
);
4396 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4397 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4398 const SLTG_TypeInfoTail
*pTITail
)
4400 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4401 if (pTIHeader
->href_table
!= 0xffffffff)
4402 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4405 if (pTITail
->vars_off
!= 0xffff)
4406 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4408 if (pTITail
->funcs_off
!= 0xffff)
4409 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4411 if (pTITail
->impls_off
!= 0xffff)
4412 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4414 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4415 * of dispinterface functions including the IDispatch ones, so
4416 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4417 pTI
->cbSizeVft
= pTI
->cFuncs
* pTI
->pTypeLib
->ptr_size
;
4419 heap_free(ref_lookup
);
4420 if (TRACE_ON(typelib
))
4421 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4424 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4425 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4426 const SLTG_TypeInfoTail
*pTITail
)
4428 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4431 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4432 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4433 const SLTG_TypeInfoTail
*pTITail
)
4435 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4436 if (pTIHeader
->href_table
!= 0xffffffff)
4437 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4440 if (pTITail
->vars_off
!= 0xffff)
4441 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4443 if (pTITail
->funcs_off
!= 0xffff)
4444 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4445 heap_free(ref_lookup
);
4446 if (TRACE_ON(typelib
))
4450 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4451 manageable copy of it into this */
4464 } SLTG_InternalOtherTypeInfo
;
4466 /****************************************************************************
4467 * ITypeLib2_Constructor_SLTG
4469 * loading a SLTG typelib from an in-memory image
4471 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4473 ITypeLibImpl
*pTypeLibImpl
;
4474 SLTG_Header
*pHeader
;
4475 SLTG_BlkEntry
*pBlkEntry
;
4479 LPVOID pBlk
, pFirstBlk
;
4480 SLTG_LibBlk
*pLibBlk
;
4481 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4482 char *pAfterOTIBlks
= NULL
;
4483 char *pNameTable
, *ptr
;
4486 ITypeInfoImpl
**ppTypeInfoImpl
;
4488 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4491 pTypeLibImpl
= TypeLibImpl_Constructor();
4492 if (!pTypeLibImpl
) return NULL
;
4496 TRACE_(typelib
)("header:\n");
4497 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4498 pHeader
->nrOfFileBlks
);
4499 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4500 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4501 pHeader
->SLTG_magic
);
4505 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4506 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4508 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4509 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4511 /* Next we have a magic block */
4512 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4514 /* Let's see if we're still in sync */
4515 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4516 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4517 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4520 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4521 sizeof(SLTG_DIR_MAGIC
))) {
4522 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4526 pIndex
= (SLTG_Index
*)(pMagic
+1);
4528 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4530 pFirstBlk
= pPad9
+ 1;
4532 /* We'll set up a ptr to the main library block, which is the last one. */
4534 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4535 pBlkEntry
[order
].next
!= 0;
4536 order
= pBlkEntry
[order
].next
- 1, i
++) {
4537 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4541 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4543 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4548 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4550 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4553 ptr
= (char*)pLibBlk
+ len
;
4555 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4559 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4561 w
= *(WORD
*)(ptr
+ 2);
4564 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4565 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4566 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4568 w
= *(WORD
*)(ptr
+ 4 + len
);
4570 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4572 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4573 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4574 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4576 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4577 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4578 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4580 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4581 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4584 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4585 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4586 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4587 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4588 len
+= sizeof(SLTG_OtherTypeInfo
);
4592 pAfterOTIBlks
= ptr
;
4594 /* Skip this WORD and get the next DWORD */
4595 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4597 /* Now add this to pLibBLk look at what we're pointing at and
4598 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4599 dust and we should be pointing at the beginning of the name
4602 pNameTable
= (char*)pLibBlk
+ len
;
4604 switch(*(WORD
*)pNameTable
) {
4611 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4615 pNameTable
+= 0x216;
4619 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4621 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4624 /* Hopefully we now have enough ptrs set up to actually read in
4625 some TypeInfos. It's not clear which order to do them in, so
4626 I'll just follow the links along the BlkEntry chain and read
4627 them in the order in which they are in the file */
4629 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4630 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4632 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4633 pBlkEntry
[order
].next
!= 0;
4634 order
= pBlkEntry
[order
].next
- 1, i
++) {
4636 SLTG_TypeInfoHeader
*pTIHeader
;
4637 SLTG_TypeInfoTail
*pTITail
;
4638 SLTG_MemberHeader
*pMemHeader
;
4640 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4641 FIXME_(typelib
)("Index strings don't match\n");
4642 heap_free(pOtherTypeInfoBlks
);
4647 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4648 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4649 heap_free(pOtherTypeInfoBlks
);
4652 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4653 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4654 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4656 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4657 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4658 (*ppTypeInfoImpl
)->index
= i
;
4659 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4660 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4661 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4662 (*ppTypeInfoImpl
)->typekind
= pTIHeader
->typekind
;
4663 (*ppTypeInfoImpl
)->wMajorVerNum
= pTIHeader
->major_version
;
4664 (*ppTypeInfoImpl
)->wMinorVerNum
= pTIHeader
->minor_version
;
4665 (*ppTypeInfoImpl
)->wTypeFlags
=
4666 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4668 if((*ppTypeInfoImpl
)->wTypeFlags
& TYPEFLAG_FDUAL
)
4669 (*ppTypeInfoImpl
)->typekind
= TKIND_DISPATCH
;
4671 if((pTIHeader
->typeflags1
& 7) != 2)
4672 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4673 if(pTIHeader
->typeflags3
!= 2)
4674 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4676 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4677 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4678 typekind_desc
[pTIHeader
->typekind
],
4679 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4680 (*ppTypeInfoImpl
)->wTypeFlags
);
4682 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4684 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4686 (*ppTypeInfoImpl
)->cbAlignment
= pTITail
->cbAlignment
;
4687 (*ppTypeInfoImpl
)->cbSizeInstance
= pTITail
->cbSizeInstance
;
4688 (*ppTypeInfoImpl
)->cbSizeVft
= pTITail
->cbSizeVft
;
4690 switch(pTIHeader
->typekind
) {
4692 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4693 pTIHeader
, pTITail
);
4697 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4698 pTIHeader
, pTITail
);
4701 case TKIND_INTERFACE
:
4702 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4703 pTIHeader
, pTITail
);
4707 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4708 pTIHeader
, pTITail
);
4712 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4713 pTIHeader
, pTITail
);
4716 case TKIND_DISPATCH
:
4717 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4718 pTIHeader
, pTITail
);
4722 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4723 pTIHeader
, pTITail
);
4727 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4732 /* could get cFuncs, cVars and cImplTypes from here
4733 but we've already set those */
4734 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4750 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4753 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4754 FIXME("Somehow processed %d TypeInfos\n", i
);
4755 heap_free(pOtherTypeInfoBlks
);
4759 heap_free(pOtherTypeInfoBlks
);
4760 return &pTypeLibImpl
->ITypeLib2_iface
;
4763 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4765 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4767 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4769 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4770 IsEqualIID(riid
,&IID_ITypeLib
)||
4771 IsEqualIID(riid
,&IID_ITypeLib2
))
4773 *ppv
= &This
->ITypeLib2_iface
;
4775 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4776 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4778 *ppv
= &This
->ICreateTypeLib2_iface
;
4783 TRACE("-- Interface: E_NOINTERFACE\n");
4784 return E_NOINTERFACE
;
4787 IUnknown_AddRef((IUnknown
*)*ppv
);
4791 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4793 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4794 ULONG ref
= InterlockedIncrement(&This
->ref
);
4796 TRACE("(%p) ref=%u\n", This
, ref
);
4801 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4803 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4804 ULONG ref
= InterlockedDecrement(&This
->ref
);
4806 TRACE("(%p) ref=%u\n",This
, ref
);
4810 TLBImpLib
*pImpLib
, *pImpLibNext
;
4811 TLBRefType
*ref_type
;
4812 TLBString
*tlbstr
, *tlbstr_next
;
4813 TLBGuid
*tlbguid
, *tlbguid_next
;
4817 /* remove cache entry */
4820 TRACE("removing from cache list\n");
4821 EnterCriticalSection(&cache_section
);
4822 if(This
->entry
.next
)
4823 list_remove(&This
->entry
);
4824 LeaveCriticalSection(&cache_section
);
4825 heap_free(This
->path
);
4827 TRACE(" destroying ITypeLib(%p)\n",This
);
4829 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4830 list_remove(&tlbstr
->entry
);
4831 SysFreeString(tlbstr
->str
);
4835 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4836 list_remove(&tlbstr
->entry
);
4837 SysFreeString(tlbstr
->str
);
4841 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4842 list_remove(&tlbguid
->entry
);
4846 TLB_FreeCustData(&This
->custdata_list
);
4848 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4849 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4850 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4852 heap_free(This
->pTypeDesc
);
4854 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4856 if (pImpLib
->pImpTypeLib
)
4857 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4858 SysFreeString(pImpLib
->name
);
4860 list_remove(&pImpLib
->entry
);
4864 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4866 list_remove(&ref_type
->entry
);
4867 heap_free(ref_type
);
4870 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4871 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4872 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4874 heap_free(This
->typeinfos
);
4882 /* ITypeLib::GetTypeInfoCount
4884 * Returns the number of type descriptions in the type library
4886 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4888 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4889 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4890 return This
->TypeInfoCount
;
4893 /* ITypeLib::GetTypeInfo
4895 * retrieves the specified type description in the library.
4897 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4900 ITypeInfo
**ppTInfo
)
4902 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4904 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4907 return E_INVALIDARG
;
4909 if(index
>= This
->TypeInfoCount
)
4910 return TYPE_E_ELEMENTNOTFOUND
;
4912 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4913 ITypeInfo_AddRef(*ppTInfo
);
4919 /* ITypeLibs::GetTypeInfoType
4921 * Retrieves the type of a type description.
4923 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4928 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4930 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4933 return E_INVALIDARG
;
4935 if(index
>= This
->TypeInfoCount
)
4936 return TYPE_E_ELEMENTNOTFOUND
;
4938 *pTKind
= This
->typeinfos
[index
]->typekind
;
4943 /* ITypeLib::GetTypeInfoOfGuid
4945 * Retrieves the type description that corresponds to the specified GUID.
4948 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4951 ITypeInfo
**ppTInfo
)
4953 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4956 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4958 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4959 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4960 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4961 ITypeInfo_AddRef(*ppTInfo
);
4966 return TYPE_E_ELEMENTNOTFOUND
;
4969 /* ITypeLib::GetLibAttr
4971 * Retrieves the structure that contains the library's attributes.
4974 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4978 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4980 TRACE("(%p, %p)\n", This
, attr
);
4982 if (!attr
) return E_INVALIDARG
;
4984 *attr
= heap_alloc(sizeof(**attr
));
4985 if (!*attr
) return E_OUTOFMEMORY
;
4987 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4988 (*attr
)->lcid
= This
->set_lcid
;
4989 (*attr
)->syskind
= This
->syskind
;
4990 (*attr
)->wMajorVerNum
= This
->ver_major
;
4991 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4992 (*attr
)->wLibFlags
= This
->libflags
;
4997 /* ITypeLib::GetTypeComp
4999 * Enables a client compiler to bind to a library's types, variables,
5000 * constants, and global functions.
5003 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
5005 ITypeComp
**ppTComp
)
5007 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5009 TRACE("(%p)->(%p)\n",This
,ppTComp
);
5010 *ppTComp
= &This
->ITypeComp_iface
;
5011 ITypeComp_AddRef(*ppTComp
);
5016 /* ITypeLib::GetDocumentation
5018 * Retrieves the library's documentation string, the complete Help file name
5019 * and path, and the context identifier for the library Help topic in the Help
5022 * On a successful return all non-null BSTR pointers will have been set,
5025 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
5029 BSTR
*pBstrDocString
,
5030 DWORD
*pdwHelpContext
,
5031 BSTR
*pBstrHelpFile
)
5033 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5034 HRESULT result
= E_INVALIDARG
;
5037 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
5039 pBstrName
, pBstrDocString
,
5040 pdwHelpContext
, pBstrHelpFile
);
5044 /* documentation for the typelib */
5049 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
5057 if (This
->DocString
)
5059 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
5063 *pBstrDocString
= NULL
;
5067 *pdwHelpContext
= This
->dwHelpContext
;
5073 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5077 *pBstrHelpFile
= NULL
;
5084 /* for a typeinfo */
5085 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5087 if(SUCCEEDED(result
))
5089 result
= ITypeInfo_GetDocumentation(pTInfo
,
5093 pdwHelpContext
, pBstrHelpFile
);
5095 ITypeInfo_Release(pTInfo
);
5100 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5102 if (pBstrName
) SysFreeString (*pBstrName
);
5104 return STG_E_INSUFFICIENTMEMORY
;
5109 * Indicates whether a passed-in string contains the name of a type or member
5110 * described in the library.
5113 static HRESULT WINAPI
ITypeLib2_fnIsName(
5119 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5121 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5123 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5127 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5128 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5129 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5130 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5131 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5133 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5134 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5135 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5136 goto ITypeLib2_fnIsName_exit
;
5139 for(vrc
= 0; vrc
< pTInfo
->cVars
; ++vrc
){
5140 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5141 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5147 ITypeLib2_fnIsName_exit
:
5148 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5149 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5154 /* ITypeLib::FindName
5156 * Finds occurrences of a type description in a type library. This may be used
5157 * to quickly verify that a name exists in a type library.
5160 static HRESULT WINAPI
ITypeLib2_fnFindName(
5164 ITypeInfo
**ppTInfo
,
5168 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5173 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5175 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5176 return E_INVALIDARG
;
5178 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5179 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
) {
5180 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5184 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
5185 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5186 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5189 if(!TLB_str_memcmp(name
, func
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
5190 for(pc
= 0; pc
< func
->funcdesc
.cParams
; pc
++) {
5191 if(!TLB_str_memcmp(name
, func
->pParamDesc
[pc
].Name
, len
))
5192 goto ITypeLib2_fnFindName_exit
;
5196 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->cVars
, name
);
5198 goto ITypeLib2_fnFindName_exit
;
5201 ITypeLib2_fnFindName_exit
:
5202 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5203 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5206 TRACE("found %d typeinfos\n", count
);
5213 /* ITypeLib::ReleaseTLibAttr
5215 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5218 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5220 TLIBATTR
*pTLibAttr
)
5222 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5223 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5224 heap_free(pTLibAttr
);
5227 /* ITypeLib2::GetCustData
5229 * gets the custom data
5231 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5236 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5237 TLBCustData
*pCData
;
5239 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5241 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5243 return TYPE_E_ELEMENTNOTFOUND
;
5245 VariantInit(pVarVal
);
5246 VariantCopy(pVarVal
, &pCData
->data
);
5251 /* ITypeLib2::GetLibStatistics
5253 * Returns statistics about a type library that are required for efficient
5254 * sizing of hash tables.
5257 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5259 ULONG
*pcUniqueNames
,
5260 ULONG
*pcchUniqueNames
)
5262 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5264 FIXME("(%p): stub!\n", This
);
5266 if(pcUniqueNames
) *pcUniqueNames
=1;
5267 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5271 /* ITypeLib2::GetDocumentation2
5273 * Retrieves the library's documentation string, the complete Help file name
5274 * and path, the localization context to use, and the context ID for the
5275 * library Help topic in the Help file.
5278 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5282 BSTR
*pbstrHelpString
,
5283 DWORD
*pdwHelpStringContext
,
5284 BSTR
*pbstrHelpStringDll
)
5286 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5290 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5292 /* the help string should be obtained from the helpstringdll,
5293 * using the _DLLGetDocumentation function, based on the supplied
5294 * lcid. Nice to do sometime...
5298 /* documentation for the typelib */
5300 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5301 if(pdwHelpStringContext
)
5302 *pdwHelpStringContext
=This
->dwHelpContext
;
5303 if(pbstrHelpStringDll
)
5304 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5310 /* for a typeinfo */
5311 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5313 if(SUCCEEDED(result
))
5315 ITypeInfo2
* pTInfo2
;
5316 result
= ITypeInfo_QueryInterface(pTInfo
,
5318 (LPVOID
*) &pTInfo2
);
5320 if(SUCCEEDED(result
))
5322 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5326 pdwHelpStringContext
,
5327 pbstrHelpStringDll
);
5329 ITypeInfo2_Release(pTInfo2
);
5332 ITypeInfo_Release(pTInfo
);
5338 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5340 TLBCustData
*pCData
;
5344 ct
= list_count(custdata_list
);
5346 pCustData
->prgCustData
= heap_alloc_zero(ct
* sizeof(CUSTDATAITEM
));
5347 if(!pCustData
->prgCustData
)
5348 return E_OUTOFMEMORY
;
5350 pCustData
->cCustData
= ct
;
5352 cdi
= pCustData
->prgCustData
;
5353 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5354 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5355 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5363 /* ITypeLib2::GetAllCustData
5365 * Gets all custom data items for the library.
5368 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5370 CUSTDATA
*pCustData
)
5372 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5373 TRACE("(%p)->(%p)\n", This
, pCustData
);
5374 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5377 static const ITypeLib2Vtbl tlbvt
= {
5378 ITypeLib2_fnQueryInterface
,
5380 ITypeLib2_fnRelease
,
5381 ITypeLib2_fnGetTypeInfoCount
,
5382 ITypeLib2_fnGetTypeInfo
,
5383 ITypeLib2_fnGetTypeInfoType
,
5384 ITypeLib2_fnGetTypeInfoOfGuid
,
5385 ITypeLib2_fnGetLibAttr
,
5386 ITypeLib2_fnGetTypeComp
,
5387 ITypeLib2_fnGetDocumentation
,
5389 ITypeLib2_fnFindName
,
5390 ITypeLib2_fnReleaseTLibAttr
,
5392 ITypeLib2_fnGetCustData
,
5393 ITypeLib2_fnGetLibStatistics
,
5394 ITypeLib2_fnGetDocumentation2
,
5395 ITypeLib2_fnGetAllCustData
5399 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5401 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5403 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5406 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5408 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5410 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5413 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5415 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5417 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5420 static HRESULT WINAPI
ITypeLibComp_fnBind(
5425 ITypeInfo
** ppTInfo
,
5426 DESCKIND
* pDescKind
,
5429 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5430 BOOL typemismatch
= FALSE
;
5433 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5435 *pDescKind
= DESCKIND_NONE
;
5436 pBindPtr
->lptcomp
= NULL
;
5439 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5440 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5441 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5443 /* FIXME: check wFlags here? */
5444 /* FIXME: we should use a hash table to look this info up using lHash
5445 * instead of an O(n) search */
5446 if ((pTypeInfo
->typekind
== TKIND_ENUM
) ||
5447 (pTypeInfo
->typekind
== TKIND_MODULE
))
5449 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5451 *pDescKind
= DESCKIND_TYPECOMP
;
5452 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5453 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5454 TRACE("module or enum: %s\n", debugstr_w(szName
));
5459 if ((pTypeInfo
->typekind
== TKIND_MODULE
) ||
5460 (pTypeInfo
->typekind
== TKIND_ENUM
))
5462 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5465 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5466 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5468 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5471 else if (hr
== TYPE_E_TYPEMISMATCH
)
5472 typemismatch
= TRUE
;
5475 if ((pTypeInfo
->typekind
== TKIND_COCLASS
) &&
5476 (pTypeInfo
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5478 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5480 ITypeInfo
*subtypeinfo
;
5482 DESCKIND subdesckind
;
5484 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5485 &subtypeinfo
, &subdesckind
, &subbindptr
);
5486 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5488 TYPEDESC tdesc_appobject
;
5489 const VARDESC vardesc_appobject
=
5492 NULL
, /* lpstrSchema */
5507 VAR_STATIC
/* varkind */
5510 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5511 tdesc_appobject
.vt
= VT_USERDEFINED
;
5513 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5515 /* cleanup things filled in by Bind call so we can put our
5516 * application object data in there instead */
5517 switch (subdesckind
)
5519 case DESCKIND_FUNCDESC
:
5520 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5522 case DESCKIND_VARDESC
:
5523 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5528 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5530 if (pTypeInfo
->hreftype
== -1)
5531 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5533 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5537 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5538 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5539 ITypeInfo_AddRef(*ppTInfo
);
5542 else if (hr
== TYPE_E_TYPEMISMATCH
)
5543 typemismatch
= TRUE
;
5549 TRACE("type mismatch %s\n", debugstr_w(szName
));
5550 return TYPE_E_TYPEMISMATCH
;
5554 TRACE("name not found %s\n", debugstr_w(szName
));
5559 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5563 ITypeInfo
** ppTInfo
,
5564 ITypeComp
** ppTComp
)
5566 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5567 ITypeInfoImpl
*info
;
5569 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5571 if(!szName
|| !ppTInfo
|| !ppTComp
)
5572 return E_INVALIDARG
;
5574 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5581 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5582 ITypeInfo_AddRef(*ppTInfo
);
5583 *ppTComp
= &info
->ITypeComp_iface
;
5584 ITypeComp_AddRef(*ppTComp
);
5589 static const ITypeCompVtbl tlbtcvt
=
5592 ITypeLibComp_fnQueryInterface
,
5593 ITypeLibComp_fnAddRef
,
5594 ITypeLibComp_fnRelease
,
5596 ITypeLibComp_fnBind
,
5597 ITypeLibComp_fnBindType
5600 /*================== ITypeInfo(2) Methods ===================================*/
5601 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5603 ITypeInfoImpl
*pTypeInfoImpl
;
5605 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5608 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5609 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5610 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5611 pTypeInfoImpl
->ref
= 0;
5612 pTypeInfoImpl
->hreftype
= -1;
5613 pTypeInfoImpl
->memidConstructor
= MEMBERID_NIL
;
5614 pTypeInfoImpl
->memidDestructor
= MEMBERID_NIL
;
5615 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5616 list_init(pTypeInfoImpl
->pcustdata_list
);
5618 TRACE("(%p)\n", pTypeInfoImpl
);
5619 return pTypeInfoImpl
;
5622 /* ITypeInfo::QueryInterface
5624 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5629 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5631 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5634 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5635 IsEqualIID(riid
,&IID_ITypeInfo
)||
5636 IsEqualIID(riid
,&IID_ITypeInfo2
))
5638 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5639 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5640 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5643 ITypeInfo2_AddRef(iface
);
5644 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5647 TRACE("-- Interface: E_NOINTERFACE\n");
5648 return E_NOINTERFACE
;
5651 /* ITypeInfo::AddRef
5653 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5655 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5656 ULONG ref
= InterlockedIncrement(&This
->ref
);
5658 TRACE("(%p)->ref is %u\n",This
, ref
);
5660 if (ref
== 1 /* incremented from 0 */)
5661 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5666 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5670 TRACE("destroying ITypeInfo(%p)\n",This
);
5672 for (i
= 0; i
< This
->cFuncs
; ++i
)
5675 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5676 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5678 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5679 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5680 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5681 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5683 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5684 heap_free(pFInfo
->pParamDesc
);
5685 TLB_FreeCustData(&pFInfo
->custdata_list
);
5687 heap_free(This
->funcdescs
);
5689 for(i
= 0; i
< This
->cVars
; ++i
)
5691 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5692 if (pVInfo
->vardesc_create
) {
5693 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5694 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5695 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5696 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5698 TLB_FreeCustData(&pVInfo
->custdata_list
);
5700 heap_free(This
->vardescs
);
5702 if(This
->impltypes
){
5703 for (i
= 0; i
< This
->cImplTypes
; ++i
){
5704 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5705 TLB_FreeCustData(&pImpl
->custdata_list
);
5707 heap_free(This
->impltypes
);
5710 TLB_FreeCustData(&This
->custdata_list
);
5715 /* ITypeInfo::Release
5717 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5719 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5720 ULONG ref
= InterlockedDecrement(&This
->ref
);
5722 TRACE("(%p)->(%u)\n",This
, ref
);
5726 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5727 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5728 if (not_attached_to_typelib
)
5730 /* otherwise This will be freed when typelib is freed */
5736 /* ITypeInfo::GetTypeAttr
5738 * Retrieves a TYPEATTR structure that contains the attributes of the type
5742 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5743 LPTYPEATTR
*ppTypeAttr
)
5745 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5748 TRACE("(%p)\n",This
);
5750 size
= sizeof(**ppTypeAttr
);
5751 if (This
->typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5752 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5754 *ppTypeAttr
= heap_alloc(size
);
5756 return E_OUTOFMEMORY
;
5758 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5759 (*ppTypeAttr
)->lcid
= This
->lcid
;
5760 (*ppTypeAttr
)->memidConstructor
= This
->memidConstructor
;
5761 (*ppTypeAttr
)->memidDestructor
= This
->memidDestructor
;
5762 (*ppTypeAttr
)->lpstrSchema
= This
->lpstrSchema
;
5763 (*ppTypeAttr
)->cbSizeInstance
= This
->cbSizeInstance
;
5764 (*ppTypeAttr
)->typekind
= This
->typekind
;
5765 (*ppTypeAttr
)->cFuncs
= This
->cFuncs
;
5766 (*ppTypeAttr
)->cVars
= This
->cVars
;
5767 (*ppTypeAttr
)->cImplTypes
= This
->cImplTypes
;
5768 (*ppTypeAttr
)->cbSizeVft
= This
->cbSizeVft
;
5769 (*ppTypeAttr
)->cbAlignment
= This
->cbAlignment
;
5770 (*ppTypeAttr
)->wTypeFlags
= This
->wTypeFlags
;
5771 (*ppTypeAttr
)->wMajorVerNum
= This
->wMajorVerNum
;
5772 (*ppTypeAttr
)->wMinorVerNum
= This
->wMinorVerNum
;
5773 (*ppTypeAttr
)->idldescType
= This
->idldescType
;
5775 if (This
->tdescAlias
)
5776 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5777 This
->tdescAlias
, *ppTypeAttr
+ 1);
5779 (*ppTypeAttr
)->tdescAlias
.vt
= VT_EMPTY
;
5780 (*ppTypeAttr
)->tdescAlias
.u
.lptdesc
= NULL
;
5783 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5784 /* This should include all the inherited funcs */
5785 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5786 /* This is always the size of IDispatch's vtbl */
5787 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5788 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5793 /* ITypeInfo::GetTypeComp
5795 * Retrieves the ITypeComp interface for the type description, which enables a
5796 * client compiler to bind to the type description's members.
5799 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5800 ITypeComp
* *ppTComp
)
5802 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5804 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5806 *ppTComp
= &This
->ITypeComp_iface
;
5807 ITypeComp_AddRef(*ppTComp
);
5811 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5813 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5814 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5815 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5819 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5822 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5823 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5825 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5826 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5827 *buffer
+= sizeof(PARAMDESCEX
);
5828 *pparamdescex_dest
= *pparamdescex_src
;
5829 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5830 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5831 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5832 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5835 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5839 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5841 UINT len
= SysStringLen(str
), i
;
5842 for (i
= 0; i
< len
; ++i
)
5848 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5850 if (V_VT(var
) == VT_INT
)
5851 return VariantChangeType(var
, var
, 0, VT_I4
);
5852 else if (V_VT(var
) == VT_UINT
)
5853 return VariantChangeType(var
, var
, 0, VT_UI4
);
5854 else if (V_VT(var
) == VT_BSTR
)
5855 return TLB_SanitizeBSTR(V_BSTR(var
));
5860 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5862 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5863 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5866 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5870 SIZE_T size
= sizeof(*src
);
5874 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5875 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5876 for (i
= 0; i
< src
->cParams
; i
++)
5878 size
+= sizeof(ELEMDESC
);
5879 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5882 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5883 if (!dest
) return E_OUTOFMEMORY
;
5886 if (dispinterface
) /* overwrite funckind */
5887 dest
->funckind
= FUNC_DISPATCH
;
5888 buffer
= (char *)(dest
+ 1);
5890 dest
->oVft
= dest
->oVft
& 0xFFFC;
5892 if (dest
->cScodes
) {
5893 dest
->lprgscode
= (SCODE
*)buffer
;
5894 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5895 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5897 dest
->lprgscode
= NULL
;
5899 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5902 SysFreeString((BSTR
)dest
);
5906 if (dest
->cParams
) {
5907 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5908 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5909 for (i
= 0; i
< src
->cParams
; i
++)
5911 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5917 /* undo the above actions */
5918 for (i
= i
- 1; i
>= 0; i
--)
5919 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5920 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5921 SysFreeString((BSTR
)dest
);
5925 dest
->lprgelemdescParam
= NULL
;
5927 /* special treatment for dispinterfaces: this makes functions appear
5928 * to return their [retval] value when it is really returning an
5930 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5932 if (dest
->cParams
&&
5933 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5935 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5936 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5938 ERR("elemdesc should have started with VT_PTR instead of:\n");
5940 dump_ELEMDESC(elemdesc
);
5941 return E_UNEXPECTED
;
5944 /* copy last parameter to the return value. we are using a flat
5945 * buffer so there is no danger of leaking memory in
5947 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5949 /* remove the last parameter */
5953 /* otherwise this function is made to appear to have no return
5955 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5963 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5965 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5966 if (var_desc
->varkind
== VAR_CONST
)
5967 VariantClear(var_desc
->u
.lpvarValue
);
5968 SysFreeString((BSTR
)var_desc
);
5971 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5973 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5975 if (index
>= This
->cFuncs
)
5976 return TYPE_E_ELEMENTNOTFOUND
;
5978 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5982 /* internal function to make the inherited interfaces' methods appear
5983 * part of the interface */
5984 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5985 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5987 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5989 UINT implemented_funcs
= 0;
5994 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5998 ITypeInfo
*pSubTypeInfo
;
6001 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
6005 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
6008 &sub_funcs
, hrefoffset
);
6009 implemented_funcs
+= sub_funcs
;
6010 ITypeInfo_Release(pSubTypeInfo
);
6013 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
6017 *funcs
= implemented_funcs
+ This
->cFuncs
;
6021 if (index
< implemented_funcs
)
6022 return E_INVALIDARG
;
6023 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
6027 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
6029 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
6032 switch (pTypeDesc
->vt
)
6034 case VT_USERDEFINED
:
6035 pTypeDesc
->u
.hreftype
+= hrefoffset
;
6039 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
6042 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
6050 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
6053 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6054 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
6055 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
6058 /* ITypeInfo::GetFuncDesc
6060 * Retrieves the FUNCDESC structure that contains information about a
6061 * specified function.
6064 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
6065 LPFUNCDESC
*ppFuncDesc
)
6067 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6068 const FUNCDESC
*internal_funcdesc
;
6070 UINT hrefoffset
= 0;
6072 TRACE("(%p) index %d\n", This
, index
);
6075 return E_INVALIDARG
;
6077 if (This
->needs_layout
)
6078 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6080 if (This
->typekind
== TKIND_DISPATCH
)
6081 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
6082 &internal_funcdesc
, NULL
,
6085 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6086 &internal_funcdesc
);
6089 WARN("description for function %d not found\n", index
);
6093 hr
= TLB_AllocAndInitFuncDesc(
6096 This
->typekind
== TKIND_DISPATCH
);
6098 if ((This
->typekind
== TKIND_DISPATCH
) && hrefoffset
)
6099 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6101 TRACE("-- 0x%08x\n", hr
);
6105 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6109 SIZE_T size
= sizeof(*src
);
6112 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6113 if (src
->varkind
== VAR_CONST
)
6114 size
+= sizeof(VARIANT
);
6115 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6117 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6118 if (!dest
) return E_OUTOFMEMORY
;
6121 buffer
= (char *)(dest
+ 1);
6122 if (src
->lpstrSchema
)
6125 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6126 len
= strlenW(src
->lpstrSchema
);
6127 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6128 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6131 if (src
->varkind
== VAR_CONST
)
6135 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6136 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6137 buffer
+= sizeof(VARIANT
);
6138 VariantInit(dest
->u
.lpvarValue
);
6139 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6142 SysFreeString((BSTR
)dest
);
6146 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6149 if (src
->varkind
== VAR_CONST
)
6150 VariantClear(dest
->u
.lpvarValue
);
6151 SysFreeString((BSTR
)dest
);
6158 /* ITypeInfo::GetVarDesc
6160 * Retrieves a VARDESC structure that describes the specified variable.
6163 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6164 LPVARDESC
*ppVarDesc
)
6166 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6167 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6169 TRACE("(%p) index %d\n", This
, index
);
6171 if(index
>= This
->cVars
)
6172 return TYPE_E_ELEMENTNOTFOUND
;
6174 if (This
->needs_layout
)
6175 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6177 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6180 /* ITypeInfo_GetNames
6182 * Retrieves the variable with the specified member ID (or the name of the
6183 * property or method and its parameters) that correspond to the specified
6186 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6187 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6189 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6190 const TLBFuncDesc
*pFDesc
;
6191 const TLBVarDesc
*pVDesc
;
6193 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6196 return E_INVALIDARG
;
6200 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
6203 if(!cMaxNames
|| !pFDesc
->Name
)
6206 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6209 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6210 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6212 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6218 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
6221 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6226 if(This
->impltypes
&&
6227 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
6228 /* recursive search */
6231 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6232 if(SUCCEEDED(result
))
6234 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6235 ITypeInfo_Release(pTInfo
);
6238 WARN("Could not search inherited interface!\n");
6242 WARN("no names found\n");
6245 return TYPE_E_ELEMENTNOTFOUND
;
6251 /* ITypeInfo::GetRefTypeOfImplType
6253 * If a type description describes a COM class, it retrieves the type
6254 * description of the implemented interface types. For an interface,
6255 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6259 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6264 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6267 TRACE("(%p) index %d\n", This
, index
);
6268 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6272 /* only valid on dual interfaces;
6273 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6276 if (This
->wTypeFlags
& TYPEFLAG_FDUAL
)
6282 hr
= TYPE_E_ELEMENTNOTFOUND
;
6285 else if(index
== 0 && This
->typekind
== TKIND_DISPATCH
)
6287 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6288 *pRefType
= This
->pTypeLib
->dispatch_href
;
6292 if(index
>= This
->cImplTypes
)
6293 hr
= TYPE_E_ELEMENTNOTFOUND
;
6295 *pRefType
= This
->impltypes
[index
].hRef
;
6296 if(This
->typekind
== TKIND_INTERFACE
)
6304 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6306 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6312 /* ITypeInfo::GetImplTypeFlags
6314 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6315 * or base interface in a type description.
6317 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6318 UINT index
, INT
*pImplTypeFlags
)
6320 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6322 TRACE("(%p) index %d\n", This
, index
);
6325 return E_INVALIDARG
;
6327 if(This
->typekind
== TKIND_DISPATCH
&& index
== 0){
6328 *pImplTypeFlags
= 0;
6332 if(index
>= This
->cImplTypes
)
6333 return TYPE_E_ELEMENTNOTFOUND
;
6335 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6341 * Maps between member names and member IDs, and parameter names and
6344 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6345 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6347 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6348 const TLBVarDesc
*pVDesc
;
6352 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6355 /* init out parameters in case of failure */
6356 for (i
= 0; i
< cNames
; i
++)
6357 pMemId
[i
] = MEMBERID_NIL
;
6359 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
) {
6361 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6362 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6363 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6364 for(i
=1; i
< cNames
; i
++){
6365 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6366 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6368 if( j
<pFDesc
->funcdesc
.cParams
)
6371 ret
=DISP_E_UNKNOWNNAME
;
6373 TRACE("-- 0x%08x\n", ret
);
6377 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, *rgszNames
);
6380 *pMemId
= pVDesc
->vardesc
.memid
;
6383 /* not found, see if it can be found in an inherited interface */
6384 if(This
->impltypes
) {
6385 /* recursive search */
6387 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6389 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6390 ITypeInfo_Release(pTInfo
);
6393 WARN("Could not search inherited interface!\n");
6395 WARN("no names found\n");
6396 return DISP_E_UNKNOWNNAME
;
6402 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6403 __ASM_GLOBAL_FUNC( call_method
,
6405 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6406 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6407 "movl %esp,%ebp\n\t"
6408 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6410 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6412 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6413 "movl 12(%ebp),%edx\n\t"
6414 "movl %esp,%edi\n\t"
6417 "subl %edx,%edi\n\t"
6418 "andl $~15,%edi\n\t"
6419 "movl %edi,%esp\n\t"
6420 "movl 12(%ebp),%ecx\n\t"
6421 "movl 16(%ebp),%esi\n\t"
6424 "1:\tcall *8(%ebp)\n\t"
6425 "subl %esp,%edi\n\t"
6426 "movl 20(%ebp),%ecx\n\t"
6427 "movl %edi,(%ecx)\n\t"
6428 "leal -8(%ebp),%esp\n\t"
6430 __ASM_CFI(".cfi_same_value %edi\n\t")
6432 __ASM_CFI(".cfi_same_value %esi\n\t")
6434 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6435 __ASM_CFI(".cfi_same_value %ebp\n\t")
6438 /* same function but returning floating point */
6439 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6441 /* ITypeInfo::Invoke
6443 * Invokes a method, or accesses a property of an object, that implements the
6444 * interface described by the type description.
6447 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6451 if (TRACE_ON(ole
)) {
6453 TRACE("Calling %p(",func
);
6454 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6455 if (nrargs
> 30) TRACE("...");
6462 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6465 FIXME("unsupported calling convention %d\n",callconv
);
6469 TRACE("returns %08x\n",res
);
6473 #elif defined(__x86_64__)
6475 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6476 __ASM_GLOBAL_FUNC( call_method
,
6478 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6479 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6480 "movq %rsp,%rbp\n\t"
6481 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6483 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6485 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6486 "movq %rcx,%rax\n\t"
6489 "cmovgq %rdx,%rcx\n\t"
6490 "leaq 0(,%rcx,8),%rdx\n\t"
6491 "subq %rdx,%rsp\n\t"
6492 "andq $~15,%rsp\n\t"
6493 "movq %rsp,%rdi\n\t"
6496 "movq 0(%rsp),%rcx\n\t"
6497 "movq 8(%rsp),%rdx\n\t"
6498 "movq 16(%rsp),%r8\n\t"
6499 "movq 24(%rsp),%r9\n\t"
6500 "movq %rcx,%xmm0\n\t"
6501 "movq %rdx,%xmm1\n\t"
6502 "movq %r8,%xmm2\n\t"
6503 "movq %r9,%xmm3\n\t"
6505 "leaq -16(%rbp),%rsp\n\t"
6507 __ASM_CFI(".cfi_same_value %rdi\n\t")
6509 __ASM_CFI(".cfi_same_value %rsi\n\t")
6510 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6512 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6513 __ASM_CFI(".cfi_same_value %rbp\n\t")
6516 /* same function but returning floating point */
6517 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6519 #endif /* __x86_64__ */
6521 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6524 ITypeInfo
*tinfo2
= NULL
;
6525 TYPEATTR
*tattr
= NULL
;
6527 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6530 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6532 tdesc
->u
.hreftype
, hr
);
6535 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6538 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6539 ITypeInfo_Release(tinfo2
);
6543 switch (tattr
->typekind
)
6550 tdesc
= &tattr
->tdescAlias
;
6551 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6554 case TKIND_INTERFACE
:
6555 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6561 case TKIND_DISPATCH
:
6570 FIXME("TKIND_RECORD unhandled.\n");
6575 FIXME("TKIND_UNION unhandled.\n");
6580 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6584 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6585 ITypeInfo_Release(tinfo2
);
6589 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6593 /* enforce only one level of pointer indirection */
6594 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6596 tdesc
= tdesc
->u
.lptdesc
;
6598 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6599 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6600 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6601 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6602 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6604 VARTYPE vt_userdefined
= 0;
6605 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6606 if (tdesc
->vt
== VT_PTR
)
6608 vt_userdefined
= VT_BYREF
;
6609 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6611 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6613 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6614 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6616 *vt
|= vt_userdefined
;
6628 case VT_USERDEFINED
:
6629 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6636 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6637 hr
= DISP_E_BADVARTYPE
;
6641 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6656 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6662 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6666 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6668 ITypeInfo_Release(tinfo2
);
6672 switch(tattr
->typekind
) {
6674 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6677 case TKIND_INTERFACE
:
6678 case TKIND_DISPATCH
:
6679 *guid
= tattr
->guid
;
6683 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6684 hres
= E_UNEXPECTED
;
6687 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6688 ITypeInfo_Release(tinfo2
);
6692 /***********************************************************************
6693 * DispCallFunc (OLEAUT32.@)
6695 * Invokes a function of the specified calling convention, passing the
6696 * specified arguments and returns the result.
6699 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6700 * oVft [I] The offset in the vtable. See notes.
6701 * cc [I] Calling convention of the function to call.
6702 * vtReturn [I] The return type of the function.
6703 * cActuals [I] Number of parameters.
6704 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6705 * prgpvarg [I] The arguments to pass.
6706 * pvargResult [O] The return value of the function. Can be NULL.
6710 * Failure: HRESULT code.
6713 * The HRESULT return value of this function is not affected by the return
6714 * value of the user supplied function, which is returned in pvargResult.
6716 * If pvInstance is NULL then a non-object function is to be called and oVft
6717 * is the address of the function to call.
6719 * The cc parameter can be one of the following values:
6732 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6733 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6736 int argspos
, stack_offset
;
6741 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6742 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6743 pvargResult
, V_VT(pvargResult
));
6745 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6747 FIXME("unsupported calling convention %d\n",cc
);
6748 return E_INVALIDARG
;
6751 /* maximum size for an argument is sizeof(VARIANT) */
6752 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6754 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6758 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6759 func
= vtable
[oVft
/sizeof(void *)];
6760 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6762 else func
= (void *)oVft
;
6764 for (i
= 0; i
< cActuals
; i
++)
6766 VARIANT
*arg
= prgpvarg
[i
];
6777 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6778 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6782 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6783 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6785 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6786 args
[argspos
++] = V_BOOL(arg
);
6789 args
[argspos
++] = V_UI4(arg
);
6792 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6799 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6802 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6806 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6810 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6811 call_method( func
, argspos
, args
, &stack_offset
);
6816 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6819 WARN("invalid return type %u\n", vtReturn
);
6821 return E_INVALIDARG
;
6823 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6827 if (stack_offset
&& cc
== CC_STDCALL
)
6829 WARN( "stack pointer off by %d\n", stack_offset
);
6830 return DISP_E_BADCALLEE
;
6832 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6833 TRACE("retval: "); dump_Variant(pvargResult
);
6836 #elif defined(__x86_64__)
6842 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6843 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6844 pvargResult
, V_VT(pvargResult
));
6846 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6848 FIXME("unsupported calling convention %d\n",cc
);
6849 return E_INVALIDARG
;
6852 /* maximum size for an argument is sizeof(DWORD_PTR) */
6853 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6855 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6859 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6860 func
= vtable
[oVft
/sizeof(void *)];
6861 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6863 else func
= (void *)oVft
;
6865 for (i
= 0; i
< cActuals
; i
++)
6867 VARIANT
*arg
= prgpvarg
[i
];
6873 args
[argspos
++] = (ULONG_PTR
)arg
;
6875 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6876 args
[argspos
++] = V_BOOL(arg
);
6879 args
[argspos
++] = V_UI8(arg
);
6882 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6889 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6893 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6897 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6898 call_method( func
, argspos
, args
);
6901 WARN("invalid return type %u\n", vtReturn
);
6903 return E_INVALIDARG
;
6905 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6909 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6910 TRACE("retval: "); dump_Variant(pvargResult
);
6914 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6915 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6920 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6922 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6925 #define INVBUF_ELEMENT_SIZE \
6926 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6927 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6928 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6929 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6930 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6931 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6932 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6933 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6935 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6940 DISPPARAMS
*pDispParams
,
6941 VARIANT
*pVarResult
,
6942 EXCEPINFO
*pExcepInfo
,
6945 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6947 unsigned int var_index
;
6950 const TLBFuncDesc
*pFuncInfo
;
6953 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6954 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6957 if( This
->wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6958 return DISP_E_MEMBERNOTFOUND
;
6962 ERR("NULL pDispParams not allowed\n");
6963 return E_INVALIDARG
;
6966 dump_DispParms(pDispParams
);
6968 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6970 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6971 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6972 return E_INVALIDARG
;
6975 /* we do this instead of using GetFuncDesc since it will return a fake
6976 * FUNCDESC for dispinterfaces and we want the real function description */
6977 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
6978 pFuncInfo
= &This
->funcdescs
[fdc
];
6979 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6980 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6981 !func_restricted( &pFuncInfo
->funcdesc
))
6985 if (fdc
< This
->cFuncs
) {
6986 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6990 TRACE("invoking:\n");
6991 dump_TLBFuncDescOne(pFuncInfo
);
6994 switch (func_desc
->funckind
) {
6995 case FUNC_PUREVIRTUAL
:
6996 case FUNC_VIRTUAL
: {
6997 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6999 VARIANT retval
; /* pointer for storing byref retvals in */
7000 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7001 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7002 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7003 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7004 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7005 UINT vargs_converted
=0;
7009 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7011 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7013 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7014 hres
= DISP_E_PARAMNOTFOUND
;
7019 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7021 ERR("functions with the vararg attribute do not support named arguments\n");
7022 hres
= DISP_E_NONAMEDARGS
;
7026 for (i
= 0; i
< func_desc
->cParams
; i
++)
7028 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7029 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7034 TRACE("changing args\n");
7035 for (i
= 0; i
< func_desc
->cParams
; i
++)
7037 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7038 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7039 VARIANTARG
*src_arg
;
7041 if (wParamFlags
& PARAMFLAG_FLCID
)
7044 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7046 V_I4(arg
) = This
->pTypeLib
->lcid
;
7055 for (j
= 0; j
< cNamedArgs
; j
++)
7056 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7058 src_arg
= &pDispParams
->rgvarg
[j
];
7063 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7065 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7069 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7071 /* under most conditions the caller is not allowed to
7072 * pass in a dispparam arg in the index of what would be
7073 * the retval parameter. however, there is an exception
7074 * where the extra parameter is used in an extra
7075 * IDispatch::Invoke below */
7076 if ((i
< pDispParams
->cArgs
) &&
7077 ((func_desc
->cParams
!= 1) || !pVarResult
||
7078 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7080 hres
= DISP_E_BADPARAMCOUNT
;
7084 /* note: this check is placed so that if the caller passes
7085 * in a VARIANTARG for the retval we just ignore it, like
7087 if (i
== func_desc
->cParams
- 1)
7090 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7091 memset(arg
, 0, sizeof(*arg
));
7092 V_VT(arg
) = rgvt
[i
];
7093 memset(&retval
, 0, sizeof(retval
));
7094 V_BYREF(arg
) = &retval
;
7098 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7099 hres
= E_UNEXPECTED
;
7105 dump_Variant(src_arg
);
7107 if(rgvt
[i
]!=V_VT(src_arg
))
7109 if (rgvt
[i
] == VT_VARIANT
)
7110 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7111 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7113 if (rgvt
[i
] == V_VT(src_arg
))
7114 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7117 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7118 if (wParamFlags
& PARAMFLAG_FIN
)
7119 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7120 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7122 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7124 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
7127 SAFEARRAYBOUND bound
;
7131 bound
.cElements
= pDispParams
->cArgs
-i
;
7132 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7134 ERR("SafeArrayCreate failed\n");
7137 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7140 ERR("SafeArrayAccessData failed with %x\n", hres
);
7141 SafeArrayDestroy(a
);
7144 for (j
= 0; j
< bound
.cElements
; j
++)
7145 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7146 hres
= SafeArrayUnaccessData(a
);
7149 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7150 SafeArrayDestroy(a
);
7153 V_ARRAY(&rgvarg
[i
]) = a
;
7154 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7156 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7158 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7159 if (wParamFlags
& PARAMFLAG_FIN
)
7160 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7162 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7163 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7164 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7166 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7168 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7169 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7173 /* FIXME: this doesn't work for VT_BYREF arguments if
7174 * they are not the same type as in the paramdesc */
7175 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7176 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7177 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7182 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
7183 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
7184 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
7187 prgpvarg
[i
] = &rgvarg
[i
];
7191 prgpvarg
[i
] = src_arg
;
7194 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7195 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7196 && V_UNKNOWN(prgpvarg
[i
])) {
7197 IUnknown
*userdefined_iface
;
7200 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7204 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7206 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7210 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7211 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7214 else if (wParamFlags
& PARAMFLAG_FOPT
)
7217 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7218 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7220 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7226 VARIANTARG
*missing_arg
;
7227 /* if the function wants a pointer to a variant then
7228 * set that up, otherwise just pass the VT_ERROR in
7229 * the argument by value */
7230 if (rgvt
[i
] & VT_BYREF
)
7232 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7233 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7234 V_VARIANTREF(arg
) = missing_arg
;
7238 V_VT(missing_arg
) = VT_ERROR
;
7239 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7244 hres
= DISP_E_BADPARAMCOUNT
;
7248 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7250 /* VT_VOID is a special case for return types, so it is not
7251 * handled in the general function */
7252 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7253 V_VT(&varresult
) = VT_EMPTY
;
7256 V_VT(&varresult
) = 0;
7257 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7258 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7261 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7262 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7263 prgpvarg
, &varresult
);
7265 vargs_converted
= 0;
7267 for (i
= 0; i
< func_desc
->cParams
; i
++)
7269 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7270 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7272 if (wParamFlags
& PARAMFLAG_FLCID
)
7274 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7278 TRACE("[retval] value: ");
7279 dump_Variant(prgpvarg
[i
]);
7284 VariantInit(pVarResult
);
7285 /* deref return value */
7286 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7289 VARIANT_ClearInd(prgpvarg
[i
]);
7291 else if (vargs_converted
< pDispParams
->cArgs
)
7293 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7294 if (wParamFlags
& PARAMFLAG_FOUT
)
7296 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7298 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7302 ERR("failed to convert param %d to vt %d\n", i
,
7303 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7308 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7309 func_desc
->cParamsOpt
< 0 &&
7310 i
== func_desc
->cParams
-1)
7312 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7315 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7318 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7321 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7324 ERR("SafeArrayAccessData failed with %x\n", hres
);
7327 for (j
= 0; j
<= ubound
; j
++)
7328 VariantClear(&v
[j
]);
7329 hres
= SafeArrayUnaccessData(a
);
7332 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7336 VariantClear(&rgvarg
[i
]);
7339 else if (wParamFlags
& PARAMFLAG_FOPT
)
7341 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7342 VariantClear(&rgvarg
[i
]);
7345 VariantClear(&missing_arg
[i
]);
7348 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7350 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7351 hres
= DISP_E_EXCEPTION
;
7354 IErrorInfo
*pErrorInfo
;
7355 pExcepInfo
->scode
= V_ERROR(&varresult
);
7356 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7358 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7359 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7360 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7361 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7363 IErrorInfo_Release(pErrorInfo
);
7367 if (V_VT(&varresult
) != VT_ERROR
)
7369 TRACE("varresult value: ");
7370 dump_Variant(&varresult
);
7374 VariantClear(pVarResult
);
7375 *pVarResult
= varresult
;
7378 VariantClear(&varresult
);
7381 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7382 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7383 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7384 (pDispParams
->cArgs
!= 0))
7386 if (V_VT(pVarResult
) == VT_DISPATCH
)
7388 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7389 /* Note: not VariantClear; we still need the dispatch
7390 * pointer to be valid */
7391 VariantInit(pVarResult
);
7392 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7393 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7394 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7395 IDispatch_Release(pDispatch
);
7399 VariantClear(pVarResult
);
7400 hres
= DISP_E_NOTACOLLECTION
;
7408 case FUNC_DISPATCH
: {
7411 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7412 if (SUCCEEDED(hres
)) {
7413 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7414 hres
= IDispatch_Invoke(
7415 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7416 pVarResult
,pExcepInfo
,pArgErr
7419 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7420 IDispatch_Release(disp
);
7422 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7426 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7431 TRACE("-- 0x%08x\n", hres
);
7434 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7437 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7438 if(FAILED(hres
)) return hres
;
7440 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7441 dump_VARDESC(var_desc
);
7442 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7446 /* not found, look for it in inherited interfaces */
7447 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7448 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7449 if(This
->impltypes
) {
7450 /* recursive search */
7452 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7453 if(SUCCEEDED(hres
)){
7454 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7455 ITypeInfo_Release(pTInfo
);
7458 WARN("Could not search inherited interface!\n");
7461 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7462 return DISP_E_MEMBERNOTFOUND
;
7465 /* ITypeInfo::GetDocumentation
7467 * Retrieves the documentation string, the complete Help file name and path,
7468 * and the context ID for the Help topic for a specified type description.
7470 * (Can be tested by the Visual Basic Editor in Word for instance.)
7472 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7473 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7474 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7476 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7477 const TLBFuncDesc
*pFDesc
;
7478 const TLBVarDesc
*pVDesc
;
7479 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7480 " HelpContext(%p) HelpFile(%p)\n",
7481 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7482 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7484 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7486 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7488 *pdwHelpContext
=This
->dwHelpContext
;
7490 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7492 }else {/* for a member */
7493 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7496 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7498 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7500 *pdwHelpContext
=pFDesc
->helpcontext
;
7502 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7505 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7508 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7510 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7512 *pdwHelpContext
=pVDesc
->HelpContext
;
7514 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7519 if(This
->impltypes
&&
7520 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
7521 /* recursive search */
7524 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7525 if(SUCCEEDED(result
)) {
7526 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7527 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7528 ITypeInfo_Release(pTInfo
);
7531 WARN("Could not search inherited interface!\n");
7534 WARN("member %d not found\n", memid
);
7535 return TYPE_E_ELEMENTNOTFOUND
;
7538 /* ITypeInfo::GetDllEntry
7540 * Retrieves a description or specification of an entry point for a function
7543 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7544 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7547 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7548 const TLBFuncDesc
*pFDesc
;
7550 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7552 if (pBstrDllName
) *pBstrDllName
= NULL
;
7553 if (pBstrName
) *pBstrName
= NULL
;
7554 if (pwOrdinal
) *pwOrdinal
= 0;
7556 if (This
->typekind
!= TKIND_MODULE
)
7557 return TYPE_E_BADMODULEKIND
;
7559 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7561 dump_TypeInfo(This
);
7563 dump_TLBFuncDescOne(pFDesc
);
7566 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7568 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7570 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7578 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7581 return TYPE_E_ELEMENTNOTFOUND
;
7584 /* internal function to make the inherited interfaces' methods appear
7585 * part of the interface */
7586 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7587 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7589 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7592 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7594 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7596 ITypeInfo
*pSubTypeInfo
;
7598 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7602 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7604 ITypeInfo_Release(pSubTypeInfo
);
7608 *hRefType
-= DISPATCH_HREF_OFFSET
;
7610 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7611 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7616 /* ITypeInfo::GetRefTypeInfo
7618 * If a type description references other type descriptions, it retrieves
7619 * the referenced type descriptions.
7621 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7624 ITypeInfo
**ppTInfo
)
7626 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7627 HRESULT result
= E_FAIL
;
7630 return E_INVALIDARG
;
7632 if ((INT
)hRefType
< 0) {
7633 ITypeInfoImpl
*pTypeInfoImpl
;
7635 if (!(This
->wTypeFlags
& TYPEFLAG_FDUAL
) ||
7636 !(This
->typekind
== TKIND_INTERFACE
||
7637 This
->typekind
== TKIND_DISPATCH
))
7638 return TYPE_E_ELEMENTNOTFOUND
;
7640 /* when we meet a DUAL typeinfo, we must create the alternate
7643 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7645 *pTypeInfoImpl
= *This
;
7646 pTypeInfoImpl
->ref
= 0;
7647 list_init(&pTypeInfoImpl
->custdata_list
);
7649 if (This
->typekind
== TKIND_INTERFACE
)
7650 pTypeInfoImpl
->typekind
= TKIND_DISPATCH
;
7652 pTypeInfoImpl
->typekind
= TKIND_INTERFACE
;
7654 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7655 /* the AddRef implicitly adds a reference to the parent typelib, which
7656 * stops the copied data from being destroyed until the new typeinfo's
7657 * refcount goes to zero, but we need to signal to the new instance to
7658 * not free its data structures when it is destroyed */
7659 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7661 ITypeInfo_AddRef(*ppTInfo
);
7664 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7665 (This
->typekind
== TKIND_DISPATCH
))
7667 HREFTYPE href_dispatch
= hRefType
;
7668 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7670 TLBRefType
*ref_type
;
7671 ITypeLib
*pTLib
= NULL
;
7674 if(!(hRefType
& 0x1)){
7675 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7677 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7680 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7681 ITypeInfo_AddRef(*ppTInfo
);
7687 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7689 if(ref_type
->reference
== (hRefType
& (~0x3)))
7692 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7694 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7698 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7700 TRACE("internal reference\n");
7701 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7703 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7704 TRACE("typeinfo in imported typelib that is already loaded\n");
7705 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7706 ITypeLib_AddRef(pTLib
);
7711 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7713 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7714 ref_type
->pImpTLInfo
->wVersionMajor
,
7715 ref_type
->pImpTLInfo
->wVersionMinor
,
7716 This
->pTypeLib
->syskind
,
7717 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7719 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7721 result
= LoadTypeLib(libnam
, &pTLib
);
7722 SysFreeString(libnam
);
7724 if(SUCCEEDED(result
)) {
7725 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7726 ITypeLib_AddRef(pTLib
);
7730 if(SUCCEEDED(result
)) {
7731 if(ref_type
->index
== TLB_REF_USE_GUID
)
7732 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7734 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7737 ITypeLib_Release(pTLib
);
7741 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7742 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7746 /* ITypeInfo::AddressOfMember
7748 * Retrieves the addresses of static functions or variables, such as those
7751 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7752 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7754 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7760 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7762 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7766 module
= LoadLibraryW(dll
);
7769 ERR("couldn't load %s\n", debugstr_w(dll
));
7771 SysFreeString(entry
);
7772 return STG_E_FILENOTFOUND
;
7774 /* FIXME: store library somewhere where we can free it */
7779 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7780 entryA
= heap_alloc(len
);
7781 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7783 *ppv
= GetProcAddress(module
, entryA
);
7785 ERR("function not found %s\n", debugstr_a(entryA
));
7791 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7793 ERR("function not found %d\n", ordinal
);
7797 SysFreeString(entry
);
7800 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7805 /* ITypeInfo::CreateInstance
7807 * Creates a new instance of a type that describes a component object class
7810 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7811 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7813 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7817 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7823 WARN("Not able to aggregate\n");
7824 return CLASS_E_NOAGGREGATION
;
7827 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7828 if(FAILED(hr
)) return hr
;
7830 if(pTA
->typekind
!= TKIND_COCLASS
)
7832 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7838 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7841 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7842 TRACE("GetActiveObject rets %08x\n", hr
);
7845 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7846 IUnknown_Release(pUnk
);
7851 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7852 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7856 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7860 /* ITypeInfo::GetMops
7862 * Retrieves marshalling information.
7864 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7867 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7868 FIXME("(%p %d) stub!\n", This
, memid
);
7873 /* ITypeInfo::GetContainingTypeLib
7875 * Retrieves the containing type library and the index of the type description
7876 * within that type library.
7878 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7879 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7881 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7883 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7885 *pIndex
=This
->index
;
7886 TRACE("returning pIndex=%d\n", *pIndex
);
7890 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7891 ITypeLib_AddRef(*ppTLib
);
7892 TRACE("returning ppTLib=%p\n", *ppTLib
);
7898 /* ITypeInfo::ReleaseTypeAttr
7900 * Releases a TYPEATTR previously returned by Get
7903 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7904 TYPEATTR
* pTypeAttr
)
7906 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7907 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7908 heap_free(pTypeAttr
);
7911 /* ITypeInfo::ReleaseFuncDesc
7913 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7915 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7917 FUNCDESC
*pFuncDesc
)
7919 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7922 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7924 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7925 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7926 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7928 SysFreeString((BSTR
)pFuncDesc
);
7931 /* ITypeInfo::ReleaseVarDesc
7933 * Releases a VARDESC previously returned by GetVarDesc.
7935 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7938 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7939 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7941 TLB_FreeVarDesc(pVarDesc
);
7944 /* ITypeInfo2::GetTypeKind
7946 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7949 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7950 TYPEKIND
*pTypeKind
)
7952 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7953 *pTypeKind
=This
->typekind
;
7954 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7958 /* ITypeInfo2::GetTypeFlags
7960 * Returns the type flags without any allocations. This returns a DWORD type
7961 * flag, which expands the type flags without growing the TYPEATTR (type
7965 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7967 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7968 *pTypeFlags
=This
->wTypeFlags
;
7969 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7973 /* ITypeInfo2::GetFuncIndexOfMemId
7974 * Binds to a specific member based on a known DISPID, where the member name
7975 * is not known (for example, when binding to a default member).
7978 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7979 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7981 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7985 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
7986 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7987 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7990 if(fdc
< This
->cFuncs
) {
7994 result
= TYPE_E_ELEMENTNOTFOUND
;
7996 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7997 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8001 /* TypeInfo2::GetVarIndexOfMemId
8003 * Binds to a specific member based on a known DISPID, where the member name
8004 * is not known (for example, when binding to a default member).
8007 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8008 MEMBERID memid
, UINT
*pVarIndex
)
8010 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8011 TLBVarDesc
*pVarInfo
;
8013 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8015 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8017 return TYPE_E_ELEMENTNOTFOUND
;
8019 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8024 /* ITypeInfo2::GetCustData
8026 * Gets the custom data
8028 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8033 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8034 TLBCustData
*pCData
;
8036 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8038 if(!guid
|| !pVarVal
)
8039 return E_INVALIDARG
;
8041 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8043 VariantInit( pVarVal
);
8045 VariantCopy( pVarVal
, &pCData
->data
);
8047 VariantClear( pVarVal
);
8051 /* ITypeInfo2::GetFuncCustData
8053 * Gets the custom data
8055 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8061 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8062 TLBCustData
*pCData
;
8063 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8065 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8067 if(index
>= This
->cFuncs
)
8068 return TYPE_E_ELEMENTNOTFOUND
;
8070 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8072 return TYPE_E_ELEMENTNOTFOUND
;
8074 VariantInit(pVarVal
);
8075 VariantCopy(pVarVal
, &pCData
->data
);
8080 /* ITypeInfo2::GetParamCustData
8082 * Gets the custom data
8084 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8091 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8092 TLBCustData
*pCData
;
8093 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8095 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8096 debugstr_guid(guid
), pVarVal
);
8098 if(indexFunc
>= This
->cFuncs
)
8099 return TYPE_E_ELEMENTNOTFOUND
;
8101 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8102 return TYPE_E_ELEMENTNOTFOUND
;
8104 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8106 return TYPE_E_ELEMENTNOTFOUND
;
8108 VariantInit(pVarVal
);
8109 VariantCopy(pVarVal
, &pCData
->data
);
8114 /* ITypeInfo2::GetVarCustData
8116 * Gets the custom data
8118 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8124 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8125 TLBCustData
*pCData
;
8126 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8128 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8130 if(index
>= This
->cVars
)
8131 return TYPE_E_ELEMENTNOTFOUND
;
8133 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8135 return TYPE_E_ELEMENTNOTFOUND
;
8137 VariantInit(pVarVal
);
8138 VariantCopy(pVarVal
, &pCData
->data
);
8143 /* ITypeInfo2::GetImplCustData
8145 * Gets the custom data
8147 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8153 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8154 TLBCustData
*pCData
;
8155 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8157 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8159 if(index
>= This
->cImplTypes
)
8160 return TYPE_E_ELEMENTNOTFOUND
;
8162 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8164 return TYPE_E_ELEMENTNOTFOUND
;
8166 VariantInit(pVarVal
);
8167 VariantCopy(pVarVal
, &pCData
->data
);
8172 /* ITypeInfo2::GetDocumentation2
8174 * Retrieves the documentation string, the complete Help file name and path,
8175 * the localization context to use, and the context ID for the library Help
8176 * topic in the Help file.
8179 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8183 BSTR
*pbstrHelpString
,
8184 DWORD
*pdwHelpStringContext
,
8185 BSTR
*pbstrHelpStringDll
)
8187 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8188 const TLBFuncDesc
*pFDesc
;
8189 const TLBVarDesc
*pVDesc
;
8190 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8191 "HelpStringContext(%p) HelpStringDll(%p)\n",
8192 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8193 pbstrHelpStringDll
);
8194 /* the help string should be obtained from the helpstringdll,
8195 * using the _DLLGetDocumentation function, based on the supplied
8196 * lcid. Nice to do sometime...
8198 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8200 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8201 if(pdwHelpStringContext
)
8202 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8203 if(pbstrHelpStringDll
)
8204 *pbstrHelpStringDll
=
8205 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8207 }else {/* for a member */
8208 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
8211 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8212 if(pdwHelpStringContext
)
8213 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8214 if(pbstrHelpStringDll
)
8215 *pbstrHelpStringDll
=
8216 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8219 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8222 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8223 if(pdwHelpStringContext
)
8224 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8225 if(pbstrHelpStringDll
)
8226 *pbstrHelpStringDll
=
8227 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8231 return TYPE_E_ELEMENTNOTFOUND
;
8234 /* ITypeInfo2::GetAllCustData
8236 * Gets all custom data items for the Type info.
8239 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8241 CUSTDATA
*pCustData
)
8243 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8245 TRACE("%p %p\n", This
, pCustData
);
8247 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8250 /* ITypeInfo2::GetAllFuncCustData
8252 * Gets all custom data items for the specified Function
8255 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8258 CUSTDATA
*pCustData
)
8260 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8261 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8263 TRACE("%p %u %p\n", This
, index
, pCustData
);
8265 if(index
>= This
->cFuncs
)
8266 return TYPE_E_ELEMENTNOTFOUND
;
8268 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8271 /* ITypeInfo2::GetAllParamCustData
8273 * Gets all custom data items for the Functions
8276 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8277 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8279 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8280 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8282 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8284 if(indexFunc
>= This
->cFuncs
)
8285 return TYPE_E_ELEMENTNOTFOUND
;
8287 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8288 return TYPE_E_ELEMENTNOTFOUND
;
8290 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8293 /* ITypeInfo2::GetAllVarCustData
8295 * Gets all custom data items for the specified Variable
8298 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8299 UINT index
, CUSTDATA
*pCustData
)
8301 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8302 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8304 TRACE("%p %u %p\n", This
, index
, pCustData
);
8306 if(index
>= This
->cVars
)
8307 return TYPE_E_ELEMENTNOTFOUND
;
8309 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8312 /* ITypeInfo2::GetAllImplCustData
8314 * Gets all custom data items for the specified implementation type
8317 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8320 CUSTDATA
*pCustData
)
8322 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8323 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8325 TRACE("%p %u %p\n", This
, index
, pCustData
);
8327 if(index
>= This
->cImplTypes
)
8328 return TYPE_E_ELEMENTNOTFOUND
;
8330 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8333 static const ITypeInfo2Vtbl tinfvt
=
8336 ITypeInfo_fnQueryInterface
,
8338 ITypeInfo_fnRelease
,
8340 ITypeInfo_fnGetTypeAttr
,
8341 ITypeInfo_fnGetTypeComp
,
8342 ITypeInfo_fnGetFuncDesc
,
8343 ITypeInfo_fnGetVarDesc
,
8344 ITypeInfo_fnGetNames
,
8345 ITypeInfo_fnGetRefTypeOfImplType
,
8346 ITypeInfo_fnGetImplTypeFlags
,
8347 ITypeInfo_fnGetIDsOfNames
,
8349 ITypeInfo_fnGetDocumentation
,
8350 ITypeInfo_fnGetDllEntry
,
8351 ITypeInfo_fnGetRefTypeInfo
,
8352 ITypeInfo_fnAddressOfMember
,
8353 ITypeInfo_fnCreateInstance
,
8354 ITypeInfo_fnGetMops
,
8355 ITypeInfo_fnGetContainingTypeLib
,
8356 ITypeInfo_fnReleaseTypeAttr
,
8357 ITypeInfo_fnReleaseFuncDesc
,
8358 ITypeInfo_fnReleaseVarDesc
,
8360 ITypeInfo2_fnGetTypeKind
,
8361 ITypeInfo2_fnGetTypeFlags
,
8362 ITypeInfo2_fnGetFuncIndexOfMemId
,
8363 ITypeInfo2_fnGetVarIndexOfMemId
,
8364 ITypeInfo2_fnGetCustData
,
8365 ITypeInfo2_fnGetFuncCustData
,
8366 ITypeInfo2_fnGetParamCustData
,
8367 ITypeInfo2_fnGetVarCustData
,
8368 ITypeInfo2_fnGetImplTypeCustData
,
8369 ITypeInfo2_fnGetDocumentation2
,
8370 ITypeInfo2_fnGetAllCustData
,
8371 ITypeInfo2_fnGetAllFuncCustData
,
8372 ITypeInfo2_fnGetAllParamCustData
,
8373 ITypeInfo2_fnGetAllVarCustData
,
8374 ITypeInfo2_fnGetAllImplTypeCustData
,
8377 /******************************************************************************
8378 * CreateDispTypeInfo [OLEAUT32.31]
8380 * Build type information for an object so it can be called through an
8381 * IDispatch interface.
8384 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8385 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8388 * This call allows an objects methods to be accessed through IDispatch, by
8389 * building an ITypeInfo object that IDispatch can use to call through.
8391 HRESULT WINAPI
CreateDispTypeInfo(
8392 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8393 LCID lcid
, /* [I] Locale Id */
8394 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8396 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8397 ITypeLibImpl
*pTypeLibImpl
;
8398 unsigned int param
, func
;
8399 TLBFuncDesc
*pFuncDesc
;
8403 pTypeLibImpl
= TypeLibImpl_Constructor();
8404 if (!pTypeLibImpl
) return E_FAIL
;
8406 pTypeLibImpl
->TypeInfoCount
= 2;
8407 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8409 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8410 pTIIface
->pTypeLib
= pTypeLibImpl
;
8411 pTIIface
->index
= 0;
8412 pTIIface
->Name
= NULL
;
8413 pTIIface
->dwHelpContext
= -1;
8414 pTIIface
->guid
= NULL
;
8415 pTIIface
->lcid
= lcid
;
8416 pTIIface
->typekind
= TKIND_INTERFACE
;
8417 pTIIface
->wMajorVerNum
= 0;
8418 pTIIface
->wMinorVerNum
= 0;
8419 pTIIface
->cbAlignment
= 2;
8420 pTIIface
->cbSizeInstance
= -1;
8421 pTIIface
->cbSizeVft
= -1;
8422 pTIIface
->cFuncs
= 0;
8423 pTIIface
->cImplTypes
= 0;
8424 pTIIface
->cVars
= 0;
8425 pTIIface
->wTypeFlags
= 0;
8426 pTIIface
->hreftype
= 0;
8428 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8429 pFuncDesc
= pTIIface
->funcdescs
;
8430 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8431 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8432 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8433 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8434 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8435 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8436 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8437 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8438 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8439 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8440 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8441 pFuncDesc
->funcdesc
.cScodes
= 0;
8442 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8443 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8444 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8445 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8446 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8447 md
->cArgs
* sizeof(ELEMDESC
));
8448 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8449 for(param
= 0; param
< md
->cArgs
; param
++) {
8450 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8451 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8453 pFuncDesc
->helpcontext
= 0;
8454 pFuncDesc
->HelpStringContext
= 0;
8455 pFuncDesc
->HelpString
= NULL
;
8456 pFuncDesc
->Entry
= NULL
;
8457 list_init(&pFuncDesc
->custdata_list
);
8462 dump_TypeInfo(pTIIface
);
8464 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8465 pTIClass
->pTypeLib
= pTypeLibImpl
;
8466 pTIClass
->index
= 1;
8467 pTIClass
->Name
= NULL
;
8468 pTIClass
->dwHelpContext
= -1;
8469 pTIClass
->guid
= NULL
;
8470 pTIClass
->lcid
= lcid
;
8471 pTIClass
->typekind
= TKIND_COCLASS
;
8472 pTIClass
->wMajorVerNum
= 0;
8473 pTIClass
->wMinorVerNum
= 0;
8474 pTIClass
->cbAlignment
= 2;
8475 pTIClass
->cbSizeInstance
= -1;
8476 pTIClass
->cbSizeVft
= -1;
8477 pTIClass
->cFuncs
= 0;
8478 pTIClass
->cImplTypes
= 1;
8479 pTIClass
->cVars
= 0;
8480 pTIClass
->wTypeFlags
= 0;
8481 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8483 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8485 ref
= heap_alloc_zero(sizeof(*ref
));
8486 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8487 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8489 dump_TypeInfo(pTIClass
);
8491 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8493 ITypeInfo_AddRef(*pptinfo
);
8494 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8500 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8502 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8504 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8507 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8509 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8511 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8514 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8516 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8518 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8521 static HRESULT WINAPI
ITypeComp_fnBind(
8526 ITypeInfo
** ppTInfo
,
8527 DESCKIND
* pDescKind
,
8530 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8531 const TLBFuncDesc
*pFDesc
;
8532 const TLBVarDesc
*pVDesc
;
8533 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8536 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8538 *pDescKind
= DESCKIND_NONE
;
8539 pBindPtr
->lpfuncdesc
= NULL
;
8542 for(fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8543 pFDesc
= &This
->funcdescs
[fdc
];
8544 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8545 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8548 /* name found, but wrong flags */
8549 hr
= TYPE_E_TYPEMISMATCH
;
8553 if (fdc
< This
->cFuncs
)
8555 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8557 &pBindPtr
->lpfuncdesc
,
8558 This
->typekind
== TKIND_DISPATCH
);
8561 *pDescKind
= DESCKIND_FUNCDESC
;
8562 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8563 ITypeInfo_AddRef(*ppTInfo
);
8566 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, szName
);
8568 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8571 *pDescKind
= DESCKIND_VARDESC
;
8572 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8573 ITypeInfo_AddRef(*ppTInfo
);
8578 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8579 /* recursive search */
8583 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8586 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8587 ITypeInfo_Release(pTInfo
);
8591 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8592 ITypeComp_Release(pTComp
);
8593 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8594 This
->typekind
== TKIND_DISPATCH
)
8596 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8597 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8598 SysFreeString((BSTR
)tmp
);
8602 WARN("Could not search inherited interface!\n");
8604 if (hr
== DISP_E_MEMBERNOTFOUND
)
8606 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8610 static HRESULT WINAPI
ITypeComp_fnBindType(
8614 ITypeInfo
** ppTInfo
,
8615 ITypeComp
** ppTComp
)
8617 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8619 /* strange behaviour (does nothing) but like the
8622 if (!ppTInfo
|| !ppTComp
)
8631 static const ITypeCompVtbl tcompvt
=
8634 ITypeComp_fnQueryInterface
,
8636 ITypeComp_fnRelease
,
8639 ITypeComp_fnBindType
8642 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8643 ICreateTypeLib2
** ppctlib
)
8648 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8650 if (!szFile
) return E_INVALIDARG
;
8652 This
= TypeLibImpl_Constructor();
8654 return E_OUTOFMEMORY
;
8656 This
->lcid
= GetSystemDefaultLCID();
8657 This
->syskind
= syskind
;
8658 This
->ptr_size
= get_ptr_size(syskind
);
8660 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8662 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8663 return E_OUTOFMEMORY
;
8665 lstrcpyW(This
->path
, szFile
);
8667 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8668 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8672 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8673 REFIID riid
, void **object
)
8675 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8677 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8680 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8682 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8684 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8687 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8689 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8691 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8694 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8695 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8697 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8698 ITypeInfoImpl
*info
;
8701 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8703 if (!ctinfo
|| !name
)
8704 return E_INVALIDARG
;
8706 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8708 return TYPE_E_NAMECONFLICT
;
8710 if (This
->typeinfos
)
8711 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8712 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8714 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8716 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8718 info
->pTypeLib
= This
;
8719 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8720 info
->index
= This
->TypeInfoCount
;
8721 info
->typekind
= kind
;
8722 info
->cbAlignment
= 4;
8724 switch(info
->typekind
) {
8726 case TKIND_INTERFACE
:
8727 case TKIND_DISPATCH
:
8729 info
->cbSizeInstance
= This
->ptr_size
;
8733 info
->cbSizeInstance
= 0;
8736 info
->cbSizeInstance
= 2;
8739 info
->cbSizeInstance
= -0x75;
8742 FIXME("unrecognized typekind %d\n", info
->typekind
);
8743 info
->cbSizeInstance
= 0xdeadbeef;
8747 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8748 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8750 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8754 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8756 ++This
->TypeInfoCount
;
8761 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8764 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8766 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8769 return E_INVALIDARG
;
8771 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8776 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8777 WORD majorVerNum
, WORD minorVerNum
)
8779 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8781 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8783 This
->ver_major
= majorVerNum
;
8784 This
->ver_minor
= minorVerNum
;
8789 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8792 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8794 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8796 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8801 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8804 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8806 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8809 return E_INVALIDARG
;
8811 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8816 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8817 LPOLESTR helpFileName
)
8819 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8821 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8824 return E_INVALIDARG
;
8826 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8831 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8834 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8836 TRACE("%p %d\n", This
, helpContext
);
8838 This
->dwHelpContext
= helpContext
;
8843 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8846 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8848 TRACE("%p %x\n", This
, lcid
);
8850 This
->set_lcid
= lcid
;
8855 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8858 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8860 TRACE("%p %x\n", This
, libFlags
);
8862 This
->libflags
= libFlags
;
8867 typedef struct tagWMSFT_SegContents
{
8870 } WMSFT_SegContents
;
8872 typedef struct tagWMSFT_TLBFile
{
8874 WMSFT_SegContents typeinfo_seg
;
8875 WMSFT_SegContents impfile_seg
;
8876 WMSFT_SegContents impinfo_seg
;
8877 WMSFT_SegContents ref_seg
;
8878 WMSFT_SegContents guidhash_seg
;
8879 WMSFT_SegContents guid_seg
;
8880 WMSFT_SegContents namehash_seg
;
8881 WMSFT_SegContents name_seg
;
8882 WMSFT_SegContents string_seg
;
8883 WMSFT_SegContents typdesc_seg
;
8884 WMSFT_SegContents arraydesc_seg
;
8885 WMSFT_SegContents custdata_seg
;
8886 WMSFT_SegContents cdguids_seg
;
8888 WMSFT_SegContents aux_seg
;
8891 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8892 WMSFT_TLBFile
*file
)
8898 file
->string_seg
.len
= 0;
8899 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8902 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8904 return E_UNEXPECTED
;
8906 size
+= sizeof(INT16
);
8908 size
= (size
+ 4) & ~0x3;
8912 file
->string_seg
.len
+= size
;
8914 /* temporarily use str->offset to store the length of the aligned,
8915 * converted string */
8919 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8922 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8925 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8926 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8928 heap_free(file
->string_seg
.data
);
8929 return E_UNEXPECTED
;
8932 *((INT16
*)data
) = size
;
8934 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8938 str
->offset
= last_offs
;
8945 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8946 WMSFT_TLBFile
*file
)
8951 MSFT_NameIntro
*last_intro
= NULL
;
8953 file
->header
.nametablecount
= 0;
8954 file
->header
.nametablechars
= 0;
8956 file
->name_seg
.len
= 0;
8957 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8960 size
= strlenW(str
->str
);
8961 file
->header
.nametablechars
+= size
;
8962 file
->header
.nametablecount
++;
8964 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8966 return E_UNEXPECTED
;
8968 size
+= sizeof(MSFT_NameIntro
);
8970 size
= (size
+ 4) & ~0x3;
8974 file
->name_seg
.len
+= size
;
8976 /* temporarily use str->offset to store the length of the aligned,
8977 * converted string */
8981 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8982 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
8985 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8987 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8989 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8990 data
+ sizeof(MSFT_NameIntro
),
8991 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8993 heap_free(file
->name_seg
.data
);
8994 return E_UNEXPECTED
;
8996 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
8998 intro
->hreftype
= -1; /* TODO? */
8999 intro
->namelen
= size
& 0xFF;
9000 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9001 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9002 intro
->namelen
|= hash
<< 16;
9003 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9004 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9006 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9007 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9009 /* update str->offset to actual value to use in other
9010 * compilation functions that require positions within
9011 * the string table */
9015 str
->offset
= last_offs
;
9020 last_intro
->hreftype
= 0; /* last one is 0? */
9025 static inline int hash_guid(GUID
*guid
)
9029 for (i
= 0; i
< 8; i
++)
9030 hash
^= ((const short *)guid
)[i
];
9035 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9038 MSFT_GuidEntry
*entry
;
9040 int hash_key
, *guidhashtab
;
9042 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9043 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9045 entry
= file
->guid_seg
.data
;
9047 guidhashtab
= file
->guidhash_seg
.data
;
9048 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9049 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9050 entry
->hreftype
= guid
->hreftype
;
9052 hash_key
= hash_guid(&guid
->guid
);
9053 entry
->next_hash
= guidhashtab
[hash_key
];
9054 guidhashtab
[hash_key
] = offs
;
9056 guid
->offset
= offs
;
9057 offs
+= sizeof(MSFT_GuidEntry
);
9064 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9067 VARTYPE arg_type
= V_VT(value
);
9070 DWORD ret
= file
->custdata_seg
.len
;
9072 if(arg_type
== VT_INT
)
9074 if(arg_type
== VT_UINT
)
9078 if(V_VT(value
) != arg_type
) {
9079 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9081 ERR("VariantChangeType failed: %08x\n", hres
);
9086 /* Check if default value can be stored in-place */
9091 if(V_UI4(&v
) > 0x3ffffff)
9104 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9107 /* have to allocate space in custdata_seg */
9116 /* Construct the data to be allocated */
9119 if(file
->custdata_seg
.data
){
9120 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9121 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9122 file
->custdata_seg
.len
+= sizeof(int) * 2;
9124 file
->custdata_seg
.len
= sizeof(int) * 2;
9125 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9128 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9129 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9131 /* TODO: Check if the encoded data is already present in custdata_seg */
9137 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9140 if(file
->custdata_seg
.data
){
9141 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9142 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9143 file
->custdata_seg
.len
+= len
;
9145 file
->custdata_seg
.len
= len
;
9146 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9149 *((unsigned short *)data
) = V_VT(value
);
9150 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9151 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9152 if(V_BSTR(&v
)[i
] <= 0x7f)
9153 data
[i
+6] = V_BSTR(&v
)[i
];
9157 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9158 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9161 /* TODO: Check if the encoded data is already present in custdata_seg */
9166 FIXME("Argument type not yet handled\n");
9171 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9173 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9175 DWORD offs
= file
->arraydesc_seg
.len
;
9179 /* TODO: we should check for duplicates, but that's harder because each
9180 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9181 * at the library-level) */
9183 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9184 if(!file
->arraydesc_seg
.data
)
9185 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9187 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9188 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
) + offs
;
9190 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9191 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9192 for(i
= 0; i
< desc
->cDims
; ++i
){
9193 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9194 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9200 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9206 VARTYPE vt
, subtype
;
9217 vt
= desc
->vt
& VT_TYPEMASK
;
9219 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9221 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9222 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9224 *out_size
+= 2 * sizeof(DWORD
);
9225 }else if(vt
== VT_CARRAY
){
9226 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9227 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9229 }else if(vt
== VT_USERDEFINED
){
9230 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9231 encoded
[1] = desc
->u
.hreftype
;
9232 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9234 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9252 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9255 data
= file
->typdesc_seg
.data
;
9256 while(offs
< file
->typdesc_seg
.len
){
9257 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9259 offs
+= sizeof(encoded
);
9262 file
->typdesc_seg
.len
+= sizeof(encoded
);
9263 if(!file
->typdesc_seg
.data
)
9264 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9266 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9268 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9273 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9275 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9276 DWORD ret
= cdguids_seg
->len
, offs
;
9277 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
9280 if(list_empty(custdata_list
))
9283 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9284 if(!cdguids_seg
->data
){
9285 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9287 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9289 offs
= ret
+ sizeof(MSFT_CDGuid
);
9290 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9291 cdguid
->GuidOffset
= cd
->guid
->offset
;
9292 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9293 cdguid
->next
= offs
;
9294 offs
+= sizeof(MSFT_CDGuid
);
9304 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9305 WMSFT_TLBFile
*file
)
9307 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9308 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9309 MSFT_VarRecord
*varrecord
;
9310 MSFT_FuncRecord
*funcrecord
;
9312 DWORD
*name
, *offsets
, offs
;
9314 for(i
= 0; i
< info
->cFuncs
; ++i
){
9315 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9317 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9319 /* optional fields */
9320 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9321 if(!list_empty(&desc
->custdata_list
))
9322 recorded_size
+= 7 * sizeof(INT
);
9323 else if(desc
->HelpStringContext
!= 0)
9324 recorded_size
+= 6 * sizeof(INT
);
9326 else if(desc
->Entry
)
9327 recorded_size
+= 3 * sizeof(INT
);
9328 else if(desc
->HelpString
)
9329 recorded_size
+= 2 * sizeof(INT
);
9330 else if(desc
->helpcontext
)
9331 recorded_size
+= sizeof(INT
);
9333 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9335 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9336 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9337 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9342 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9345 for(i
= 0; i
< info
->cVars
; ++i
){
9346 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9348 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9350 /* optional fields */
9351 if(desc
->HelpStringContext
!= 0)
9352 recorded_size
+= 5 * sizeof(INT
);
9353 else if(!list_empty(&desc
->custdata_list
))
9354 recorded_size
+= 4 * sizeof(INT
);
9356 else if(desc
->HelpString
)
9357 recorded_size
+= 2 * sizeof(INT
);
9358 else if(desc
->HelpContext
!= 0)
9359 recorded_size
+= sizeof(INT
);
9361 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9364 if(!recorded_size
&& !extra_size
)
9367 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9369 aux_seg
->len
+= recorded_size
+ extra_size
;
9371 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9374 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9376 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9378 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9380 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9383 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9384 for(i
= 0; i
< info
->cFuncs
; ++i
){
9385 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9386 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9388 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9389 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9390 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9391 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9394 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9399 * ^has_param_defaults
9400 * ^oEntry_is_intresource
9402 funcrecord
->FKCCIC
=
9403 desc
->funcdesc
.funckind
|
9404 (desc
->funcdesc
.invkind
<< 3) |
9405 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9406 (desc
->funcdesc
.callconv
<< 8);
9408 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9409 funcrecord
->FKCCIC
|= 0x2000;
9411 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9412 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9413 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9414 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9417 if(paramdefault_size
> 0)
9418 funcrecord
->FKCCIC
|= 0x1000;
9420 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9421 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9423 /* optional fields */
9425 if(!list_empty(&desc
->custdata_list
)){
9426 size
+= 7 * sizeof(INT
);
9427 funcrecord
->HelpContext
= desc
->helpcontext
;
9428 if(desc
->HelpString
)
9429 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9431 funcrecord
->oHelpString
= -1;
9433 funcrecord
->oEntry
= -1;
9434 else if(IS_INTRESOURCE(desc
->Entry
))
9435 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9437 funcrecord
->oEntry
= desc
->Entry
->offset
;
9438 funcrecord
->res9
= -1;
9439 funcrecord
->resA
= -1;
9440 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9441 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9442 }else if(desc
->HelpStringContext
!= 0){
9443 size
+= 6 * sizeof(INT
);
9444 funcrecord
->HelpContext
= desc
->helpcontext
;
9445 if(desc
->HelpString
)
9446 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9448 funcrecord
->oHelpString
= -1;
9450 funcrecord
->oEntry
= -1;
9451 else if(IS_INTRESOURCE(desc
->Entry
))
9452 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9454 funcrecord
->oEntry
= desc
->Entry
->offset
;
9455 funcrecord
->res9
= -1;
9456 funcrecord
->resA
= -1;
9457 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9458 }else if(desc
->Entry
){
9459 size
+= 3 * sizeof(INT
);
9460 funcrecord
->HelpContext
= desc
->helpcontext
;
9461 if(desc
->HelpString
)
9462 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9464 funcrecord
->oHelpString
= -1;
9466 funcrecord
->oEntry
= -1;
9467 else if(IS_INTRESOURCE(desc
->Entry
))
9468 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9470 funcrecord
->oEntry
= desc
->Entry
->offset
;
9471 }else if(desc
->HelpString
){
9472 size
+= 2 * sizeof(INT
);
9473 funcrecord
->HelpContext
= desc
->helpcontext
;
9474 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9475 }else if(desc
->helpcontext
){
9476 size
+= sizeof(INT
);
9477 funcrecord
->HelpContext
= desc
->helpcontext
;
9480 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9481 size
+= paramdefault_size
;
9483 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9484 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9486 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9487 if(desc
->pParamDesc
[j
].Name
)
9488 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9491 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9493 if(paramdefault_size
){
9494 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9495 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9496 else if(paramdefault_size
)
9501 size
+= sizeof(MSFT_ParameterInfo
);
9504 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9510 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9513 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9514 for(i
= 0; i
< info
->cVars
; ++i
){
9515 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9516 DWORD size
= 5 * sizeof(INT
);
9518 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9519 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9520 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9521 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9523 if(desc
->vardesc
.varkind
== VAR_CONST
){
9524 varrecord
->vardescsize
+= sizeof(VARIANT
);
9525 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9527 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9530 if(desc
->HelpStringContext
!= 0){
9531 size
+= 5 * sizeof(INT
);
9532 varrecord
->HelpContext
= desc
->HelpContext
;
9533 if(desc
->HelpString
)
9534 varrecord
->HelpString
= desc
->HelpString
->offset
;
9536 varrecord
->HelpString
= -1;
9537 varrecord
->res9
= -1;
9538 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9539 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9540 }else if(!list_empty(&desc
->custdata_list
)){
9541 size
+= 4 * sizeof(INT
);
9542 varrecord
->HelpContext
= desc
->HelpContext
;
9543 if(desc
->HelpString
)
9544 varrecord
->HelpString
= desc
->HelpString
->offset
;
9546 varrecord
->HelpString
= -1;
9547 varrecord
->res9
= -1;
9548 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9549 }else if(desc
->HelpString
){
9550 size
+= 2 * sizeof(INT
);
9551 varrecord
->HelpContext
= desc
->HelpContext
;
9552 if(desc
->HelpString
)
9553 varrecord
->HelpString
= desc
->HelpString
->offset
;
9555 varrecord
->HelpString
= -1;
9556 }else if(desc
->HelpContext
!= 0){
9557 size
+= sizeof(INT
);
9558 varrecord
->HelpContext
= desc
->HelpContext
;
9561 varrecord
->Info
= size
| (i
<< 16);
9567 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9570 memid
= (MEMBERID
*)varrecord
;
9571 for(i
= 0; i
< info
->cFuncs
; ++i
){
9572 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9573 *memid
= desc
->funcdesc
.memid
;
9576 for(i
= 0; i
< info
->cVars
; ++i
){
9577 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9578 *memid
= desc
->vardesc
.memid
;
9582 name
= (UINT
*)memid
;
9583 for(i
= 0; i
< info
->cFuncs
; ++i
){
9584 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9586 *name
= desc
->Name
->offset
;
9591 for(i
= 0; i
< info
->cVars
; ++i
){
9592 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9594 *name
= desc
->Name
->offset
;
9603 typedef struct tagWMSFT_RefChunk
{
9610 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9612 DWORD offs
= file
->ref_seg
.len
, i
;
9613 WMSFT_RefChunk
*chunk
;
9615 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9616 if(!file
->ref_seg
.data
)
9617 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9619 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9621 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9623 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9624 chunk
->href
= info
->impltypes
[i
].hRef
;
9625 chunk
->res04
= info
->impltypes
[i
].implflags
;
9627 if(i
< info
->cImplTypes
- 1)
9628 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9637 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9641 size
= sizeof(MSFT_TypeInfoBase
);
9644 MSFT_TypeInfoBase
*base
= (void*)data
;
9645 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9646 base
->typekind
= TKIND_DISPATCH
;
9648 base
->typekind
= info
->typekind
;
9649 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9650 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9651 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9656 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9662 base
->posguid
= info
->guid
->offset
;
9665 base
->flags
= info
->wTypeFlags
;
9667 base
->NameOffset
= info
->Name
->offset
;
9669 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9670 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9672 base
->NameOffset
= -1;
9674 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9676 base
->docstringoffs
= info
->DocString
->offset
;
9678 base
->docstringoffs
= -1;
9679 base
->helpstringcontext
= info
->dwHelpStringContext
;
9680 base
->helpcontext
= info
->dwHelpContext
;
9681 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9682 base
->cImplTypes
= info
->cImplTypes
;
9683 base
->cbSizeVft
= info
->cbSizeVft
;
9684 base
->size
= info
->cbSizeInstance
;
9685 if(info
->typekind
== TKIND_COCLASS
){
9686 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9687 }else if(info
->typekind
== TKIND_ALIAS
){
9688 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9689 }else if(info
->typekind
== TKIND_MODULE
){
9691 base
->datatype1
= info
->DllName
->offset
;
9693 base
->datatype1
= -1;
9695 if(info
->cImplTypes
> 0)
9696 base
->datatype1
= info
->impltypes
[0].hRef
;
9698 base
->datatype1
= -1;
9700 base
->datatype2
= index
; /* FIXME: i think there's more here */
9708 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9712 file
->typeinfo_seg
.len
= 0;
9713 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9714 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9715 *junk
= file
->typeinfo_seg
.len
;
9717 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9720 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9721 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9723 file
->aux_seg
.len
= 0;
9724 file
->aux_seg
.data
= NULL
;
9726 file
->typeinfo_seg
.len
= 0;
9727 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9728 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9729 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9730 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9734 typedef struct tagWMSFT_ImpFile
{
9740 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9743 WMSFT_ImpFile
*impfile
;
9745 DWORD last_offs
= 0;
9747 file
->impfile_seg
.len
= 0;
9748 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9752 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9756 path
= implib
->name
;
9757 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9759 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9762 size
+= sizeof(INT16
);
9764 size
= (size
+ 4) & ~0x3;
9768 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9771 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9773 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9774 int strlen
= 0, size
;
9776 impfile
= (WMSFT_ImpFile
*)data
;
9777 impfile
->guid_offs
= implib
->guid
->offset
;
9778 impfile
->lcid
= implib
->lcid
;
9779 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9781 data
+= sizeof(WMSFT_ImpFile
);
9784 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9788 path
= implib
->name
;
9789 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9790 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9792 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9795 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9797 size
= strlen
+ sizeof(INT16
);
9799 size
= (size
+ 4) & ~0x3;
9802 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9805 implib
->offset
= last_offs
;
9806 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9810 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9813 TLBRefType
*ref_type
;
9816 WMSFT_compile_impfile(This
, file
);
9818 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9819 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9821 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9822 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9823 if(ref_type
->index
== TLB_REF_USE_GUID
){
9824 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9825 info
->oGuid
= ref_type
->guid
->offset
;
9827 info
->oGuid
= ref_type
->index
;
9828 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9834 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9836 file
->guidhash_seg
.len
= 0x80;
9837 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9838 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9841 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9843 file
->namehash_seg
.len
= 0x200;
9844 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9845 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9848 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9850 if(contents
&& contents
->len
){
9851 segdir
->offset
= *running_offset
;
9852 segdir
->length
= contents
->len
;
9853 *running_offset
+= segdir
->length
;
9855 segdir
->offset
= -1;
9859 /* TODO: do these ever change? */
9861 segdir
->res0c
= 0xf;
9864 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9868 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9871 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9875 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9877 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9878 base
->memoffset
+= file_len
;
9885 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9887 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9888 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9889 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9890 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9891 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9892 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9893 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9894 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9895 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9896 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9897 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9898 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9899 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9900 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9903 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9905 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9907 DWORD written
, junk_size
, junk_offs
, running_offset
;
9914 TRACE("%p\n", This
);
9916 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
9917 if(This
->typeinfos
[i
]->needs_layout
)
9918 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
9920 memset(&file
, 0, sizeof(file
));
9922 file
.header
.magic1
= 0x5446534D;
9923 file
.header
.magic2
= 0x00010002;
9924 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9925 file
.header
.lcid2
= This
->set_lcid
;
9926 file
.header
.varflags
= 0x40 | This
->syskind
;
9928 file
.header
.varflags
|= 0x10;
9929 if (This
->HelpStringDll
)
9930 file
.header
.varflags
|= HELPDLLFLAG
;
9931 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
9932 file
.header
.flags
= This
->libflags
;
9933 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9934 file
.header
.helpcontext
= This
->dwHelpContext
;
9935 file
.header
.res44
= 0x20;
9936 file
.header
.res48
= 0x80;
9937 file
.header
.dispatchpos
= This
->dispatch_href
;
9939 WMSFT_compile_namehash(This
, &file
);
9940 /* do name and string compilation to get offsets for other compilations */
9941 hres
= WMSFT_compile_names(This
, &file
);
9943 WMSFT_free_file(&file
);
9947 hres
= WMSFT_compile_strings(This
, &file
);
9949 WMSFT_free_file(&file
);
9953 WMSFT_compile_guidhash(This
, &file
);
9954 hres
= WMSFT_compile_guids(This
, &file
);
9956 WMSFT_free_file(&file
);
9961 file
.header
.helpfile
= This
->HelpFile
->offset
;
9963 file
.header
.helpfile
= -1;
9966 file
.header
.helpstring
= This
->DocString
->offset
;
9968 file
.header
.helpstring
= -1;
9970 /* do some more segment compilation */
9971 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9972 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9975 file
.header
.NameOffset
= This
->Name
->offset
;
9977 file
.header
.NameOffset
= -1;
9979 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
9982 file
.header
.posguid
= This
->guid
->offset
;
9984 file
.header
.posguid
= -1;
9986 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9987 if(file
.header
.varflags
& HELPDLLFLAG
)
9988 junk_size
+= sizeof(DWORD
);
9990 junk
= heap_alloc_zero(junk_size
);
9991 if(file
.header
.varflags
& HELPDLLFLAG
){
9992 *junk
= This
->HelpStringDll
->offset
;
10001 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10002 WMSFT_compile_impinfo(This
, &file
);
10004 running_offset
= 0;
10006 TRACE("header at: 0x%x\n", running_offset
);
10007 running_offset
+= sizeof(file
.header
);
10009 TRACE("junk at: 0x%x\n", running_offset
);
10010 running_offset
+= junk_size
;
10012 TRACE("segdir at: 0x%x\n", running_offset
);
10013 running_offset
+= sizeof(file
.segdir
);
10015 TRACE("typeinfo at: 0x%x\n", running_offset
);
10016 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10018 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10019 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10021 TRACE("guidtab at: 0x%x\n", running_offset
);
10022 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10024 TRACE("reftab at: 0x%x\n", running_offset
);
10025 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10027 TRACE("impinfo at: 0x%x\n", running_offset
);
10028 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10030 TRACE("impfiles at: 0x%x\n", running_offset
);
10031 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10033 TRACE("namehashtab at: 0x%x\n", running_offset
);
10034 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10036 TRACE("nametab at: 0x%x\n", running_offset
);
10037 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10039 TRACE("stringtab at: 0x%x\n", running_offset
);
10040 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10042 TRACE("typdesc at: 0x%x\n", running_offset
);
10043 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10045 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10046 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10048 TRACE("custdata at: 0x%x\n", running_offset
);
10049 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10051 TRACE("cdguids at: 0x%x\n", running_offset
);
10052 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10054 TRACE("res0e at: 0x%x\n", running_offset
);
10055 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10057 TRACE("res0f at: 0x%x\n", running_offset
);
10058 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10060 TRACE("aux_seg at: 0x%x\n", running_offset
);
10062 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10064 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10065 FILE_ATTRIBUTE_NORMAL
, 0);
10066 if (outfile
== INVALID_HANDLE_VALUE
){
10067 WMSFT_free_file(&file
);
10069 return TYPE_E_IOERROR
;
10072 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10074 WMSFT_free_file(&file
);
10075 CloseHandle(outfile
);
10077 return TYPE_E_IOERROR
;
10080 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10083 WMSFT_free_file(&file
);
10084 CloseHandle(outfile
);
10085 return TYPE_E_IOERROR
;
10088 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10090 WMSFT_free_file(&file
);
10091 CloseHandle(outfile
);
10092 return TYPE_E_IOERROR
;
10095 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10096 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10097 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10098 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10099 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10100 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10101 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10102 WMSFT_write_segment(outfile
, &file
.name_seg
);
10103 WMSFT_write_segment(outfile
, &file
.string_seg
);
10104 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10105 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10106 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10107 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10108 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10110 WMSFT_free_file(&file
);
10112 CloseHandle(outfile
);
10117 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10120 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10121 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10125 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10126 REFGUID guid
, VARIANT
*varVal
)
10128 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10129 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
10133 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10134 ULONG helpStringContext
)
10136 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10137 FIXME("%p %u - stub\n", This
, helpStringContext
);
10141 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10144 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10145 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10148 return E_INVALIDARG
;
10150 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10155 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10156 ICreateTypeLib2_fnQueryInterface
,
10157 ICreateTypeLib2_fnAddRef
,
10158 ICreateTypeLib2_fnRelease
,
10159 ICreateTypeLib2_fnCreateTypeInfo
,
10160 ICreateTypeLib2_fnSetName
,
10161 ICreateTypeLib2_fnSetVersion
,
10162 ICreateTypeLib2_fnSetGuid
,
10163 ICreateTypeLib2_fnSetDocString
,
10164 ICreateTypeLib2_fnSetHelpFileName
,
10165 ICreateTypeLib2_fnSetHelpContext
,
10166 ICreateTypeLib2_fnSetLcid
,
10167 ICreateTypeLib2_fnSetLibFlags
,
10168 ICreateTypeLib2_fnSaveAllChanges
,
10169 ICreateTypeLib2_fnDeleteTypeInfo
,
10170 ICreateTypeLib2_fnSetCustData
,
10171 ICreateTypeLib2_fnSetHelpStringContext
,
10172 ICreateTypeLib2_fnSetHelpStringDll
10175 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10176 REFIID riid
, void **object
)
10178 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10180 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10183 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10185 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10187 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10190 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10192 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10194 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10197 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10200 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10202 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10204 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10209 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10212 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10216 TRACE("%p %x\n", This
, typeFlags
);
10218 if (typeFlags
& TYPEFLAG_FDUAL
) {
10219 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10221 ITypeInfo
*dispatch
;
10225 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10229 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10230 ITypeLib_Release(stdole
);
10234 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10235 ITypeInfo_Release(dispatch
);
10240 old_flags
= This
->wTypeFlags
;
10241 This
->wTypeFlags
= typeFlags
;
10243 hres
= ICreateTypeInfo2_LayOut(iface
);
10244 if (FAILED(hres
)) {
10245 This
->wTypeFlags
= old_flags
;
10252 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10255 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10257 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10260 return E_INVALIDARG
;
10262 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10267 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10270 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10272 TRACE("%p %d\n", This
, helpContext
);
10274 This
->dwHelpContext
= helpContext
;
10279 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10280 WORD majorVerNum
, WORD minorVerNum
)
10282 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10284 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10286 This
->wMajorVerNum
= majorVerNum
;
10287 This
->wMinorVerNum
= minorVerNum
;
10292 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10293 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10295 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10297 ITypeLib
*container
;
10298 TLBRefType
*ref_type
;
10300 TYPEATTR
*typeattr
;
10304 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10306 if (!typeInfo
|| !refType
)
10307 return E_INVALIDARG
;
10309 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10313 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10314 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10316 ITypeLib_Release(container
);
10318 *refType
= target
->hreftype
;
10323 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10324 if (FAILED(hres
)) {
10325 ITypeLib_Release(container
);
10329 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10330 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10331 implib
->lcid
== libattr
->lcid
&&
10332 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10333 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10337 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10338 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10340 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10341 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10342 implib
->name
= SysAllocString(our_container
->path
);
10344 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10345 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10347 implib
->name
= NULL
;
10348 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10352 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10353 implib
->lcid
= libattr
->lcid
;
10354 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10355 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10357 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10360 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10361 ITypeLib_Release(container
);
10363 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10368 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10369 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10370 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10371 ref_type
->tkind
== typeattr
->typekind
)
10376 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10377 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10379 ref_type
->tkind
= typeattr
->typekind
;
10380 ref_type
->pImpTLInfo
= implib
;
10381 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10383 ref_type
->index
= TLB_REF_USE_GUID
;
10385 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10387 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10390 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10392 *refType
= ref_type
->reference
| 0x1;
10394 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10395 This
->pTypeLib
->dispatch_href
= *refType
;
10400 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10401 UINT index
, FUNCDESC
*funcDesc
)
10403 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10404 TLBFuncDesc tmp_func_desc
, *func_desc
;
10409 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10411 if (!funcDesc
|| funcDesc
->oVft
& 3)
10412 return E_INVALIDARG
;
10414 switch (This
->typekind
) {
10416 if (funcDesc
->funckind
!= FUNC_STATIC
)
10417 return TYPE_E_BADMODULEKIND
;
10419 case TKIND_DISPATCH
:
10420 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10421 return TYPE_E_BADMODULEKIND
;
10424 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10425 return TYPE_E_BADMODULEKIND
;
10428 if (index
> This
->cFuncs
)
10429 return TYPE_E_ELEMENTNOTFOUND
;
10431 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10432 !funcDesc
->cParams
)
10433 return TYPE_E_INCONSISTENTPROPFUNCS
;
10436 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10437 funcDesc
->oVft
% 8 != 0)
10438 return E_INVALIDARG
;
10441 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10442 TLBFuncDesc_Constructor(&tmp_func_desc
);
10444 tmp_func_desc
.funcdesc
= *funcDesc
;
10446 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10447 tmp_func_desc
.funcdesc
.oVft
|= 1;
10449 if (funcDesc
->cScodes
) {
10450 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10451 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10453 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10455 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10456 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10457 buf_size
+= sizeof(ELEMDESC
);
10458 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10460 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10461 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10463 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10464 if (FAILED(hres
)) {
10465 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10466 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10470 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10471 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10472 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10473 if (FAILED(hres
)) {
10474 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10475 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10478 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10479 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10480 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10481 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10482 if (FAILED(hres
)) {
10483 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10484 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10490 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10492 if (This
->funcdescs
) {
10493 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10494 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10496 if (index
< This
->cFuncs
) {
10497 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10498 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10499 func_desc
= This
->funcdescs
+ index
;
10501 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10503 /* move custdata lists to the new memory location */
10504 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10506 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10507 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10508 list_init(&fd
->custdata_list
);
10510 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10511 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10516 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10518 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10519 list_init(&func_desc
->custdata_list
);
10523 This
->needs_layout
= TRUE
;
10528 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10529 UINT index
, HREFTYPE refType
)
10531 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10532 TLBImplType
*impl_type
;
10535 TRACE("%p %u %d\n", This
, index
, refType
);
10537 switch(This
->typekind
){
10538 case TKIND_COCLASS
: {
10540 FIXME("Unhandled index: -1\n");
10544 if(index
!= This
->cImplTypes
)
10545 return TYPE_E_ELEMENTNOTFOUND
;
10549 case TKIND_INTERFACE
:
10550 case TKIND_DISPATCH
:
10551 if (index
!= 0 || This
->cImplTypes
)
10552 return TYPE_E_ELEMENTNOTFOUND
;
10555 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10559 if (This
->impltypes
){
10562 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10563 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10565 if (index
< This
->cImplTypes
) {
10566 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10567 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10568 impl_type
= This
->impltypes
+ index
;
10570 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10572 /* move custdata lists to the new memory location */
10573 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10575 TLBImplType
*it
= &This
->impltypes
[i
];
10576 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10577 list_init(&it
->custdata_list
);
10579 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10580 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10585 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10587 memset(impl_type
, 0, sizeof(TLBImplType
));
10588 TLBImplType_Constructor(impl_type
);
10589 impl_type
->hRef
= refType
;
10591 ++This
->cImplTypes
;
10593 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10594 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10596 hres
= ICreateTypeInfo2_LayOut(iface
);
10603 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10604 UINT index
, INT implTypeFlags
)
10606 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10607 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10609 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10611 if (This
->typekind
!= TKIND_COCLASS
)
10612 return TYPE_E_BADMODULEKIND
;
10614 if (index
>= This
->cImplTypes
)
10615 return TYPE_E_ELEMENTNOTFOUND
;
10617 impl_type
->implflags
= implTypeFlags
;
10622 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10625 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10627 TRACE("%p %d\n", This
, alignment
);
10629 This
->cbAlignment
= alignment
;
10634 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10637 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10639 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10642 return E_INVALIDARG
;
10644 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10646 This
->lpstrSchema
= This
->Schema
->str
;
10651 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10652 UINT index
, VARDESC
*varDesc
)
10654 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10655 TLBVarDesc
*var_desc
;
10657 TRACE("%p %u %p\n", This
, index
, varDesc
);
10659 if (This
->vardescs
){
10662 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10663 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10665 if (index
< This
->cVars
) {
10666 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10667 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10668 var_desc
= This
->vardescs
+ index
;
10670 var_desc
= This
->vardescs
+ This
->cVars
;
10672 /* move custdata lists to the new memory location */
10673 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10675 TLBVarDesc
*var
= &This
->vardescs
[i
];
10676 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10677 list_init(&var
->custdata_list
);
10679 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10680 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10685 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10687 TLBVarDesc_Constructor(var_desc
);
10688 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10689 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10693 This
->needs_layout
= TRUE
;
10698 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10699 UINT index
, LPOLESTR
*names
, UINT numNames
)
10701 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10702 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10705 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10708 return E_INVALIDARG
;
10710 if (index
>= This
->cFuncs
|| numNames
== 0)
10711 return TYPE_E_ELEMENTNOTFOUND
;
10713 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10714 if(numNames
> func_desc
->funcdesc
.cParams
)
10715 return TYPE_E_ELEMENTNOTFOUND
;
10717 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10718 return TYPE_E_ELEMENTNOTFOUND
;
10720 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10721 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10722 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10723 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10724 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10725 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10727 return TYPE_E_AMBIGUOUSNAME
;
10731 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10733 for (i
= 1; i
< numNames
; ++i
) {
10734 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10735 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10741 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10742 UINT index
, LPOLESTR name
)
10744 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10746 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10749 return E_INVALIDARG
;
10751 if(index
>= This
->cVars
)
10752 return TYPE_E_ELEMENTNOTFOUND
;
10754 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10758 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10759 TYPEDESC
*tdescAlias
)
10761 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10764 TRACE("%p %p\n", This
, tdescAlias
);
10767 return E_INVALIDARG
;
10769 if(This
->typekind
!= TKIND_ALIAS
)
10770 return TYPE_E_BADMODULEKIND
;
10772 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->cbSizeInstance
, &This
->cbAlignment
);
10776 heap_free(This
->tdescAlias
);
10777 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10778 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10783 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10784 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10786 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10787 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10791 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10792 UINT index
, LPOLESTR docString
)
10794 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10795 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10797 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10800 return E_INVALIDARG
;
10802 if(index
>= This
->cFuncs
)
10803 return TYPE_E_ELEMENTNOTFOUND
;
10805 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10810 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10811 UINT index
, LPOLESTR docString
)
10813 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10814 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10816 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10819 return E_INVALIDARG
;
10821 if(index
>= This
->cVars
)
10822 return TYPE_E_ELEMENTNOTFOUND
;
10824 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10829 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10830 UINT index
, DWORD helpContext
)
10832 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10833 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10835 TRACE("%p %u %d\n", This
, index
, helpContext
);
10837 if(index
>= This
->cFuncs
)
10838 return TYPE_E_ELEMENTNOTFOUND
;
10840 func_desc
->helpcontext
= helpContext
;
10845 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10846 UINT index
, DWORD helpContext
)
10848 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10849 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10851 TRACE("%p %u %d\n", This
, index
, helpContext
);
10853 if(index
>= This
->cVars
)
10854 return TYPE_E_ELEMENTNOTFOUND
;
10856 var_desc
->HelpContext
= helpContext
;
10861 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10862 UINT index
, BSTR bstrMops
)
10864 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10865 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10869 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10872 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10874 TRACE("%p %p\n", This
, idlDesc
);
10877 return E_INVALIDARG
;
10879 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10880 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10885 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10887 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10889 TLBFuncDesc
*func_desc
;
10890 UINT user_vft
= 0, i
, depth
= 0;
10891 HRESULT hres
= S_OK
;
10893 TRACE("%p\n", This
);
10895 This
->needs_layout
= FALSE
;
10897 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10901 if (This
->typekind
== TKIND_INTERFACE
) {
10906 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10908 if (SUCCEEDED(hres
)) {
10909 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10911 if (SUCCEEDED(hres
)) {
10912 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10913 if (FAILED(hres
)) {
10914 ITypeInfo_Release(inh
);
10915 ITypeInfo_Release(tinfo
);
10918 This
->cbSizeVft
= attr
->cbSizeVft
;
10919 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10923 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10924 if(SUCCEEDED(hres
)){
10926 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10927 if(SUCCEEDED(hres
)){
10928 ITypeInfo_Release(inh
);
10932 }while(SUCCEEDED(hres
));
10935 ITypeInfo_Release(inh
);
10936 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10937 This
->cbSizeVft
= 0;
10940 ITypeInfo_Release(tinfo
);
10943 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10944 This
->cbSizeVft
= 0;
10947 ITypeInfo_Release(tinfo
);
10950 } else if (This
->typekind
== TKIND_DISPATCH
)
10951 This
->cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10953 This
->cbSizeVft
= 0;
10955 func_desc
= This
->funcdescs
;
10957 while (i
< This
->cFuncs
) {
10958 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10959 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
10961 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10962 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10964 This
->cbSizeVft
+= This
->pTypeLib
->ptr_size
;
10966 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10969 BOOL reset
= FALSE
;
10971 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10973 iter
= This
->funcdescs
;
10974 while (j
< This
->cFuncs
) {
10975 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10977 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
10980 ++func_desc
->funcdesc
.memid
;
10981 iter
= This
->funcdescs
;
10994 if (user_vft
> This
->cbSizeVft
)
10995 This
->cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
10997 for(i
= 0; i
< This
->cVars
; ++i
){
10998 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
10999 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11001 BOOL reset
= FALSE
;
11004 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11006 iter
= This
->vardescs
;
11007 while (j
< This
->cVars
) {
11008 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11010 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->cVars
;
11013 ++var_desc
->vardesc
.memid
;
11014 iter
= This
->vardescs
;
11024 ITypeInfo_Release(tinfo
);
11028 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11031 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11032 FIXME("%p %u - stub\n", This
, index
);
11036 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11037 MEMBERID memid
, INVOKEKIND invKind
)
11039 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11040 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11044 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11047 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11048 FIXME("%p %u - stub\n", This
, index
);
11052 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11055 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11056 FIXME("%p %x - stub\n", This
, memid
);
11060 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11063 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11064 FIXME("%p %u - stub\n", This
, index
);
11068 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11069 REFGUID guid
, VARIANT
*varVal
)
11073 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11075 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11077 if (!guid
|| !varVal
)
11078 return E_INVALIDARG
;
11080 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11082 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11085 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11086 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11088 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11089 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11093 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11094 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11096 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11097 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11101 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11102 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11104 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11105 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11109 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11110 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11112 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11113 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11117 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11118 ULONG helpStringContext
)
11120 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11122 TRACE("%p %u\n", This
, helpStringContext
);
11124 This
->dwHelpStringContext
= helpStringContext
;
11129 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11130 UINT index
, ULONG helpStringContext
)
11132 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11133 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11137 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11138 UINT index
, ULONG helpStringContext
)
11140 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11141 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11145 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11147 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11148 FIXME("%p - stub\n", This
);
11152 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11155 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11157 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11160 return E_INVALIDARG
;
11162 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11167 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11168 ICreateTypeInfo2_fnQueryInterface
,
11169 ICreateTypeInfo2_fnAddRef
,
11170 ICreateTypeInfo2_fnRelease
,
11171 ICreateTypeInfo2_fnSetGuid
,
11172 ICreateTypeInfo2_fnSetTypeFlags
,
11173 ICreateTypeInfo2_fnSetDocString
,
11174 ICreateTypeInfo2_fnSetHelpContext
,
11175 ICreateTypeInfo2_fnSetVersion
,
11176 ICreateTypeInfo2_fnAddRefTypeInfo
,
11177 ICreateTypeInfo2_fnAddFuncDesc
,
11178 ICreateTypeInfo2_fnAddImplType
,
11179 ICreateTypeInfo2_fnSetImplTypeFlags
,
11180 ICreateTypeInfo2_fnSetAlignment
,
11181 ICreateTypeInfo2_fnSetSchema
,
11182 ICreateTypeInfo2_fnAddVarDesc
,
11183 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11184 ICreateTypeInfo2_fnSetVarName
,
11185 ICreateTypeInfo2_fnSetTypeDescAlias
,
11186 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11187 ICreateTypeInfo2_fnSetFuncDocString
,
11188 ICreateTypeInfo2_fnSetVarDocString
,
11189 ICreateTypeInfo2_fnSetFuncHelpContext
,
11190 ICreateTypeInfo2_fnSetVarHelpContext
,
11191 ICreateTypeInfo2_fnSetMops
,
11192 ICreateTypeInfo2_fnSetTypeIdldesc
,
11193 ICreateTypeInfo2_fnLayOut
,
11194 ICreateTypeInfo2_fnDeleteFuncDesc
,
11195 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11196 ICreateTypeInfo2_fnDeleteVarDesc
,
11197 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11198 ICreateTypeInfo2_fnDeleteImplType
,
11199 ICreateTypeInfo2_fnSetCustData
,
11200 ICreateTypeInfo2_fnSetFuncCustData
,
11201 ICreateTypeInfo2_fnSetParamCustData
,
11202 ICreateTypeInfo2_fnSetVarCustData
,
11203 ICreateTypeInfo2_fnSetImplTypeCustData
,
11204 ICreateTypeInfo2_fnSetHelpStringContext
,
11205 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11206 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11207 ICreateTypeInfo2_fnInvalidate
,
11208 ICreateTypeInfo2_fnSetName
11211 /******************************************************************************
11212 * ClearCustData (OLEAUT32.171)
11214 * Clear a custom data type's data.
11217 * lpCust [I] The custom data type instance
11222 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11224 if (lpCust
&& lpCust
->cCustData
)
11226 if (lpCust
->prgCustData
)
11230 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11231 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11233 /* FIXME - Should be using a per-thread IMalloc */
11234 heap_free(lpCust
->prgCustData
);
11235 lpCust
->prgCustData
= NULL
;
11237 lpCust
->cCustData
= 0;