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; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5180 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5184 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5185 memid
[count
] = MEMBERID_NIL
;
5186 goto ITypeLib2_fnFindName_exit
;
5189 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5190 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5192 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5193 memid
[count
] = func
->funcdesc
.memid
;
5194 goto ITypeLib2_fnFindName_exit
;
5198 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->cVars
, name
);
5200 memid
[count
] = var
->vardesc
.memid
;
5201 goto ITypeLib2_fnFindName_exit
;
5205 ITypeLib2_fnFindName_exit
:
5206 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5207 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5210 TRACE("found %d typeinfos\n", count
);
5217 /* ITypeLib::ReleaseTLibAttr
5219 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5222 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5224 TLIBATTR
*pTLibAttr
)
5226 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5227 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5228 heap_free(pTLibAttr
);
5231 /* ITypeLib2::GetCustData
5233 * gets the custom data
5235 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5240 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5241 TLBCustData
*pCData
;
5243 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5245 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5247 return TYPE_E_ELEMENTNOTFOUND
;
5249 VariantInit(pVarVal
);
5250 VariantCopy(pVarVal
, &pCData
->data
);
5255 /* ITypeLib2::GetLibStatistics
5257 * Returns statistics about a type library that are required for efficient
5258 * sizing of hash tables.
5261 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5263 ULONG
*pcUniqueNames
,
5264 ULONG
*pcchUniqueNames
)
5266 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5268 FIXME("(%p): stub!\n", This
);
5270 if(pcUniqueNames
) *pcUniqueNames
=1;
5271 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5275 /* ITypeLib2::GetDocumentation2
5277 * Retrieves the library's documentation string, the complete Help file name
5278 * and path, the localization context to use, and the context ID for the
5279 * library Help topic in the Help file.
5282 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5286 BSTR
*pbstrHelpString
,
5287 DWORD
*pdwHelpStringContext
,
5288 BSTR
*pbstrHelpStringDll
)
5290 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5294 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5296 /* the help string should be obtained from the helpstringdll,
5297 * using the _DLLGetDocumentation function, based on the supplied
5298 * lcid. Nice to do sometime...
5302 /* documentation for the typelib */
5304 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5305 if(pdwHelpStringContext
)
5306 *pdwHelpStringContext
=This
->dwHelpContext
;
5307 if(pbstrHelpStringDll
)
5308 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5314 /* for a typeinfo */
5315 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5317 if(SUCCEEDED(result
))
5319 ITypeInfo2
* pTInfo2
;
5320 result
= ITypeInfo_QueryInterface(pTInfo
,
5322 (LPVOID
*) &pTInfo2
);
5324 if(SUCCEEDED(result
))
5326 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5330 pdwHelpStringContext
,
5331 pbstrHelpStringDll
);
5333 ITypeInfo2_Release(pTInfo2
);
5336 ITypeInfo_Release(pTInfo
);
5342 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5344 TLBCustData
*pCData
;
5348 ct
= list_count(custdata_list
);
5350 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5351 if(!pCustData
->prgCustData
)
5352 return E_OUTOFMEMORY
;
5354 pCustData
->cCustData
= ct
;
5356 cdi
= pCustData
->prgCustData
;
5357 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5358 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5359 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5367 /* ITypeLib2::GetAllCustData
5369 * Gets all custom data items for the library.
5372 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5374 CUSTDATA
*pCustData
)
5376 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5377 TRACE("(%p)->(%p)\n", This
, pCustData
);
5378 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5381 static const ITypeLib2Vtbl tlbvt
= {
5382 ITypeLib2_fnQueryInterface
,
5384 ITypeLib2_fnRelease
,
5385 ITypeLib2_fnGetTypeInfoCount
,
5386 ITypeLib2_fnGetTypeInfo
,
5387 ITypeLib2_fnGetTypeInfoType
,
5388 ITypeLib2_fnGetTypeInfoOfGuid
,
5389 ITypeLib2_fnGetLibAttr
,
5390 ITypeLib2_fnGetTypeComp
,
5391 ITypeLib2_fnGetDocumentation
,
5393 ITypeLib2_fnFindName
,
5394 ITypeLib2_fnReleaseTLibAttr
,
5396 ITypeLib2_fnGetCustData
,
5397 ITypeLib2_fnGetLibStatistics
,
5398 ITypeLib2_fnGetDocumentation2
,
5399 ITypeLib2_fnGetAllCustData
5403 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5405 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5407 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5410 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5412 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5414 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5417 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5419 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5421 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5424 static HRESULT WINAPI
ITypeLibComp_fnBind(
5429 ITypeInfo
** ppTInfo
,
5430 DESCKIND
* pDescKind
,
5433 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5434 BOOL typemismatch
= FALSE
;
5437 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5439 *pDescKind
= DESCKIND_NONE
;
5440 pBindPtr
->lptcomp
= NULL
;
5443 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5444 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5445 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5447 /* FIXME: check wFlags here? */
5448 /* FIXME: we should use a hash table to look this info up using lHash
5449 * instead of an O(n) search */
5450 if ((pTypeInfo
->typekind
== TKIND_ENUM
) ||
5451 (pTypeInfo
->typekind
== TKIND_MODULE
))
5453 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5455 *pDescKind
= DESCKIND_TYPECOMP
;
5456 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5457 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5458 TRACE("module or enum: %s\n", debugstr_w(szName
));
5463 if ((pTypeInfo
->typekind
== TKIND_MODULE
) ||
5464 (pTypeInfo
->typekind
== TKIND_ENUM
))
5466 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5469 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5470 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5472 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5475 else if (hr
== TYPE_E_TYPEMISMATCH
)
5476 typemismatch
= TRUE
;
5479 if ((pTypeInfo
->typekind
== TKIND_COCLASS
) &&
5480 (pTypeInfo
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5482 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5484 ITypeInfo
*subtypeinfo
;
5486 DESCKIND subdesckind
;
5488 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5489 &subtypeinfo
, &subdesckind
, &subbindptr
);
5490 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5492 TYPEDESC tdesc_appobject
;
5493 const VARDESC vardesc_appobject
=
5496 NULL
, /* lpstrSchema */
5511 VAR_STATIC
/* varkind */
5514 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5515 tdesc_appobject
.vt
= VT_USERDEFINED
;
5517 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5519 /* cleanup things filled in by Bind call so we can put our
5520 * application object data in there instead */
5521 switch (subdesckind
)
5523 case DESCKIND_FUNCDESC
:
5524 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5526 case DESCKIND_VARDESC
:
5527 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5532 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5534 if (pTypeInfo
->hreftype
== -1)
5535 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5537 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5541 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5542 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5543 ITypeInfo_AddRef(*ppTInfo
);
5546 else if (hr
== TYPE_E_TYPEMISMATCH
)
5547 typemismatch
= TRUE
;
5553 TRACE("type mismatch %s\n", debugstr_w(szName
));
5554 return TYPE_E_TYPEMISMATCH
;
5558 TRACE("name not found %s\n", debugstr_w(szName
));
5563 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5567 ITypeInfo
** ppTInfo
,
5568 ITypeComp
** ppTComp
)
5570 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5571 ITypeInfoImpl
*info
;
5573 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5575 if(!szName
|| !ppTInfo
|| !ppTComp
)
5576 return E_INVALIDARG
;
5578 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5585 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5586 ITypeInfo_AddRef(*ppTInfo
);
5587 *ppTComp
= &info
->ITypeComp_iface
;
5588 ITypeComp_AddRef(*ppTComp
);
5593 static const ITypeCompVtbl tlbtcvt
=
5596 ITypeLibComp_fnQueryInterface
,
5597 ITypeLibComp_fnAddRef
,
5598 ITypeLibComp_fnRelease
,
5600 ITypeLibComp_fnBind
,
5601 ITypeLibComp_fnBindType
5604 /*================== ITypeInfo(2) Methods ===================================*/
5605 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5607 ITypeInfoImpl
*pTypeInfoImpl
;
5609 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5612 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5613 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5614 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5615 pTypeInfoImpl
->ref
= 0;
5616 pTypeInfoImpl
->hreftype
= -1;
5617 pTypeInfoImpl
->memidConstructor
= MEMBERID_NIL
;
5618 pTypeInfoImpl
->memidDestructor
= MEMBERID_NIL
;
5619 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5620 list_init(pTypeInfoImpl
->pcustdata_list
);
5622 TRACE("(%p)\n", pTypeInfoImpl
);
5623 return pTypeInfoImpl
;
5626 /* ITypeInfo::QueryInterface
5628 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5633 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5635 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5638 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5639 IsEqualIID(riid
,&IID_ITypeInfo
)||
5640 IsEqualIID(riid
,&IID_ITypeInfo2
))
5642 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5643 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5644 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5647 ITypeInfo2_AddRef(iface
);
5648 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5651 TRACE("-- Interface: E_NOINTERFACE\n");
5652 return E_NOINTERFACE
;
5655 /* ITypeInfo::AddRef
5657 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5659 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5660 ULONG ref
= InterlockedIncrement(&This
->ref
);
5662 TRACE("(%p)->ref is %u\n",This
, ref
);
5664 if (ref
== 1 /* incremented from 0 */)
5665 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5670 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5674 TRACE("destroying ITypeInfo(%p)\n",This
);
5676 for (i
= 0; i
< This
->cFuncs
; ++i
)
5679 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5680 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5682 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5683 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5684 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5685 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5687 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5688 heap_free(pFInfo
->pParamDesc
);
5689 TLB_FreeCustData(&pFInfo
->custdata_list
);
5691 heap_free(This
->funcdescs
);
5693 for(i
= 0; i
< This
->cVars
; ++i
)
5695 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5696 if (pVInfo
->vardesc_create
) {
5697 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5698 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5699 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5700 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5702 TLB_FreeCustData(&pVInfo
->custdata_list
);
5704 heap_free(This
->vardescs
);
5706 if(This
->impltypes
){
5707 for (i
= 0; i
< This
->cImplTypes
; ++i
){
5708 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5709 TLB_FreeCustData(&pImpl
->custdata_list
);
5711 heap_free(This
->impltypes
);
5714 TLB_FreeCustData(&This
->custdata_list
);
5719 /* ITypeInfo::Release
5721 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5723 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5724 ULONG ref
= InterlockedDecrement(&This
->ref
);
5726 TRACE("(%p)->(%u)\n",This
, ref
);
5730 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5731 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5732 if (not_attached_to_typelib
)
5734 /* otherwise This will be freed when typelib is freed */
5740 /* ITypeInfo::GetTypeAttr
5742 * Retrieves a TYPEATTR structure that contains the attributes of the type
5746 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5747 LPTYPEATTR
*ppTypeAttr
)
5749 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5752 TRACE("(%p)\n",This
);
5754 size
= sizeof(**ppTypeAttr
);
5755 if (This
->typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5756 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5758 *ppTypeAttr
= heap_alloc(size
);
5760 return E_OUTOFMEMORY
;
5762 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5763 (*ppTypeAttr
)->lcid
= This
->lcid
;
5764 (*ppTypeAttr
)->memidConstructor
= This
->memidConstructor
;
5765 (*ppTypeAttr
)->memidDestructor
= This
->memidDestructor
;
5766 (*ppTypeAttr
)->lpstrSchema
= This
->lpstrSchema
;
5767 (*ppTypeAttr
)->cbSizeInstance
= This
->cbSizeInstance
;
5768 (*ppTypeAttr
)->typekind
= This
->typekind
;
5769 (*ppTypeAttr
)->cFuncs
= This
->cFuncs
;
5770 (*ppTypeAttr
)->cVars
= This
->cVars
;
5771 (*ppTypeAttr
)->cImplTypes
= This
->cImplTypes
;
5772 (*ppTypeAttr
)->cbSizeVft
= This
->cbSizeVft
;
5773 (*ppTypeAttr
)->cbAlignment
= This
->cbAlignment
;
5774 (*ppTypeAttr
)->wTypeFlags
= This
->wTypeFlags
;
5775 (*ppTypeAttr
)->wMajorVerNum
= This
->wMajorVerNum
;
5776 (*ppTypeAttr
)->wMinorVerNum
= This
->wMinorVerNum
;
5777 (*ppTypeAttr
)->idldescType
= This
->idldescType
;
5779 if (This
->tdescAlias
)
5780 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5781 This
->tdescAlias
, *ppTypeAttr
+ 1);
5783 (*ppTypeAttr
)->tdescAlias
.vt
= VT_EMPTY
;
5784 (*ppTypeAttr
)->tdescAlias
.u
.lptdesc
= NULL
;
5787 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5788 /* This should include all the inherited funcs */
5789 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5790 /* This is always the size of IDispatch's vtbl */
5791 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5792 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5797 /* ITypeInfo::GetTypeComp
5799 * Retrieves the ITypeComp interface for the type description, which enables a
5800 * client compiler to bind to the type description's members.
5803 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5804 ITypeComp
* *ppTComp
)
5806 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5808 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5810 *ppTComp
= &This
->ITypeComp_iface
;
5811 ITypeComp_AddRef(*ppTComp
);
5815 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5817 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5818 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5819 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5823 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5826 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5827 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5829 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5830 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5831 *buffer
+= sizeof(PARAMDESCEX
);
5832 *pparamdescex_dest
= *pparamdescex_src
;
5833 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5834 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5835 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5836 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5839 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5843 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5845 UINT len
= SysStringLen(str
), i
;
5846 for (i
= 0; i
< len
; ++i
)
5852 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5854 if (V_VT(var
) == VT_INT
)
5855 return VariantChangeType(var
, var
, 0, VT_I4
);
5856 else if (V_VT(var
) == VT_UINT
)
5857 return VariantChangeType(var
, var
, 0, VT_UI4
);
5858 else if (V_VT(var
) == VT_BSTR
)
5859 return TLB_SanitizeBSTR(V_BSTR(var
));
5864 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5866 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5867 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5870 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5874 SIZE_T size
= sizeof(*src
);
5878 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5879 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5880 for (i
= 0; i
< src
->cParams
; i
++)
5882 size
+= sizeof(ELEMDESC
);
5883 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5886 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5887 if (!dest
) return E_OUTOFMEMORY
;
5890 if (dispinterface
) /* overwrite funckind */
5891 dest
->funckind
= FUNC_DISPATCH
;
5892 buffer
= (char *)(dest
+ 1);
5894 dest
->oVft
= dest
->oVft
& 0xFFFC;
5896 if (dest
->cScodes
) {
5897 dest
->lprgscode
= (SCODE
*)buffer
;
5898 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5899 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5901 dest
->lprgscode
= NULL
;
5903 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5906 SysFreeString((BSTR
)dest
);
5910 if (dest
->cParams
) {
5911 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5912 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5913 for (i
= 0; i
< src
->cParams
; i
++)
5915 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5921 /* undo the above actions */
5922 for (i
= i
- 1; i
>= 0; i
--)
5923 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5924 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5925 SysFreeString((BSTR
)dest
);
5929 dest
->lprgelemdescParam
= NULL
;
5931 /* special treatment for dispinterfaces: this makes functions appear
5932 * to return their [retval] value when it is really returning an
5934 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5936 if (dest
->cParams
&&
5937 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5939 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5940 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5942 ERR("elemdesc should have started with VT_PTR instead of:\n");
5944 dump_ELEMDESC(elemdesc
);
5945 return E_UNEXPECTED
;
5948 /* copy last parameter to the return value. we are using a flat
5949 * buffer so there is no danger of leaking memory in
5951 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5953 /* remove the last parameter */
5957 /* otherwise this function is made to appear to have no return
5959 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5967 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5969 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5970 if (var_desc
->varkind
== VAR_CONST
)
5971 VariantClear(var_desc
->u
.lpvarValue
);
5972 SysFreeString((BSTR
)var_desc
);
5975 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5977 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5979 if (index
>= This
->cFuncs
)
5980 return TYPE_E_ELEMENTNOTFOUND
;
5982 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5986 /* internal function to make the inherited interfaces' methods appear
5987 * part of the interface */
5988 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5989 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5991 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5993 UINT implemented_funcs
= 0;
5998 *hrefoffset
= DISPATCH_HREF_OFFSET
;
6002 ITypeInfo
*pSubTypeInfo
;
6005 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
6009 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
6012 &sub_funcs
, hrefoffset
);
6013 implemented_funcs
+= sub_funcs
;
6014 ITypeInfo_Release(pSubTypeInfo
);
6017 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
6021 *funcs
= implemented_funcs
+ This
->cFuncs
;
6025 if (index
< implemented_funcs
)
6026 return E_INVALIDARG
;
6027 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
6031 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
6033 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
6036 switch (pTypeDesc
->vt
)
6038 case VT_USERDEFINED
:
6039 pTypeDesc
->u
.hreftype
+= hrefoffset
;
6043 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
6046 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
6054 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
6057 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6058 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
6059 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
6062 /* ITypeInfo::GetFuncDesc
6064 * Retrieves the FUNCDESC structure that contains information about a
6065 * specified function.
6068 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
6069 LPFUNCDESC
*ppFuncDesc
)
6071 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6072 const FUNCDESC
*internal_funcdesc
;
6074 UINT hrefoffset
= 0;
6076 TRACE("(%p) index %d\n", This
, index
);
6079 return E_INVALIDARG
;
6081 if (This
->needs_layout
)
6082 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6084 if (This
->typekind
== TKIND_DISPATCH
)
6085 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
6086 &internal_funcdesc
, NULL
,
6089 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6090 &internal_funcdesc
);
6093 WARN("description for function %d not found\n", index
);
6097 hr
= TLB_AllocAndInitFuncDesc(
6100 This
->typekind
== TKIND_DISPATCH
);
6102 if ((This
->typekind
== TKIND_DISPATCH
) && hrefoffset
)
6103 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6105 TRACE("-- 0x%08x\n", hr
);
6109 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6113 SIZE_T size
= sizeof(*src
);
6116 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6117 if (src
->varkind
== VAR_CONST
)
6118 size
+= sizeof(VARIANT
);
6119 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6121 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6122 if (!dest
) return E_OUTOFMEMORY
;
6125 buffer
= (char *)(dest
+ 1);
6126 if (src
->lpstrSchema
)
6129 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6130 len
= strlenW(src
->lpstrSchema
);
6131 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6132 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6135 if (src
->varkind
== VAR_CONST
)
6139 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6140 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6141 buffer
+= sizeof(VARIANT
);
6142 VariantInit(dest
->u
.lpvarValue
);
6143 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6146 SysFreeString((BSTR
)dest
);
6150 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6153 if (src
->varkind
== VAR_CONST
)
6154 VariantClear(dest
->u
.lpvarValue
);
6155 SysFreeString((BSTR
)dest
);
6162 /* ITypeInfo::GetVarDesc
6164 * Retrieves a VARDESC structure that describes the specified variable.
6167 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6168 LPVARDESC
*ppVarDesc
)
6170 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6171 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6173 TRACE("(%p) index %d\n", This
, index
);
6175 if(index
>= This
->cVars
)
6176 return TYPE_E_ELEMENTNOTFOUND
;
6178 if (This
->needs_layout
)
6179 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6181 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6184 /* ITypeInfo_GetNames
6186 * Retrieves the variable with the specified member ID (or the name of the
6187 * property or method and its parameters) that correspond to the specified
6190 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6191 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6193 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6194 const TLBFuncDesc
*pFDesc
;
6195 const TLBVarDesc
*pVDesc
;
6197 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6200 return E_INVALIDARG
;
6204 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
6207 if(!cMaxNames
|| !pFDesc
->Name
)
6210 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6213 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6214 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6216 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6222 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
6225 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6230 if(This
->impltypes
&&
6231 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
6232 /* recursive search */
6235 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6236 if(SUCCEEDED(result
))
6238 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6239 ITypeInfo_Release(pTInfo
);
6242 WARN("Could not search inherited interface!\n");
6246 WARN("no names found\n");
6249 return TYPE_E_ELEMENTNOTFOUND
;
6255 /* ITypeInfo::GetRefTypeOfImplType
6257 * If a type description describes a COM class, it retrieves the type
6258 * description of the implemented interface types. For an interface,
6259 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6263 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6268 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6271 TRACE("(%p) index %d\n", This
, index
);
6272 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6276 /* only valid on dual interfaces;
6277 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6280 if (This
->wTypeFlags
& TYPEFLAG_FDUAL
)
6286 hr
= TYPE_E_ELEMENTNOTFOUND
;
6289 else if(index
== 0 && This
->typekind
== TKIND_DISPATCH
)
6291 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6292 *pRefType
= This
->pTypeLib
->dispatch_href
;
6296 if(index
>= This
->cImplTypes
)
6297 hr
= TYPE_E_ELEMENTNOTFOUND
;
6299 *pRefType
= This
->impltypes
[index
].hRef
;
6300 if(This
->typekind
== TKIND_INTERFACE
)
6308 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6310 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6316 /* ITypeInfo::GetImplTypeFlags
6318 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6319 * or base interface in a type description.
6321 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6322 UINT index
, INT
*pImplTypeFlags
)
6324 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6326 TRACE("(%p) index %d\n", This
, index
);
6329 return E_INVALIDARG
;
6331 if(This
->typekind
== TKIND_DISPATCH
&& index
== 0){
6332 *pImplTypeFlags
= 0;
6336 if(index
>= This
->cImplTypes
)
6337 return TYPE_E_ELEMENTNOTFOUND
;
6339 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6345 * Maps between member names and member IDs, and parameter names and
6348 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6349 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6351 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6352 const TLBVarDesc
*pVDesc
;
6356 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6359 /* init out parameters in case of failure */
6360 for (i
= 0; i
< cNames
; i
++)
6361 pMemId
[i
] = MEMBERID_NIL
;
6363 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
) {
6365 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6366 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6367 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6368 for(i
=1; i
< cNames
; i
++){
6369 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6370 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6372 if( j
<pFDesc
->funcdesc
.cParams
)
6375 ret
=DISP_E_UNKNOWNNAME
;
6377 TRACE("-- 0x%08x\n", ret
);
6381 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, *rgszNames
);
6384 *pMemId
= pVDesc
->vardesc
.memid
;
6387 /* not found, see if it can be found in an inherited interface */
6388 if(This
->impltypes
) {
6389 /* recursive search */
6391 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6393 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6394 ITypeInfo_Release(pTInfo
);
6397 WARN("Could not search inherited interface!\n");
6399 WARN("no names found\n");
6400 return DISP_E_UNKNOWNNAME
;
6406 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6407 __ASM_GLOBAL_FUNC( call_method
,
6409 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6410 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6411 "movl %esp,%ebp\n\t"
6412 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6414 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6416 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6417 "movl 12(%ebp),%edx\n\t"
6418 "movl %esp,%edi\n\t"
6421 "subl %edx,%edi\n\t"
6422 "andl $~15,%edi\n\t"
6423 "movl %edi,%esp\n\t"
6424 "movl 12(%ebp),%ecx\n\t"
6425 "movl 16(%ebp),%esi\n\t"
6428 "1:\tcall *8(%ebp)\n\t"
6429 "subl %esp,%edi\n\t"
6430 "movl 20(%ebp),%ecx\n\t"
6431 "movl %edi,(%ecx)\n\t"
6432 "leal -8(%ebp),%esp\n\t"
6434 __ASM_CFI(".cfi_same_value %edi\n\t")
6436 __ASM_CFI(".cfi_same_value %esi\n\t")
6438 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6439 __ASM_CFI(".cfi_same_value %ebp\n\t")
6442 /* same function but returning floating point */
6443 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6445 /* ITypeInfo::Invoke
6447 * Invokes a method, or accesses a property of an object, that implements the
6448 * interface described by the type description.
6451 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6455 if (TRACE_ON(ole
)) {
6457 TRACE("Calling %p(",func
);
6458 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6459 if (nrargs
> 30) TRACE("...");
6466 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6469 FIXME("unsupported calling convention %d\n",callconv
);
6473 TRACE("returns %08x\n",res
);
6477 #elif defined(__x86_64__)
6479 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6480 __ASM_GLOBAL_FUNC( call_method
,
6482 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6483 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6484 "movq %rsp,%rbp\n\t"
6485 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6487 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6489 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6490 "movq %rcx,%rax\n\t"
6493 "cmovgq %rdx,%rcx\n\t"
6494 "leaq 0(,%rcx,8),%rdx\n\t"
6495 "subq %rdx,%rsp\n\t"
6496 "andq $~15,%rsp\n\t"
6497 "movq %rsp,%rdi\n\t"
6500 "movq 0(%rsp),%rcx\n\t"
6501 "movq 8(%rsp),%rdx\n\t"
6502 "movq 16(%rsp),%r8\n\t"
6503 "movq 24(%rsp),%r9\n\t"
6504 "movq %rcx,%xmm0\n\t"
6505 "movq %rdx,%xmm1\n\t"
6506 "movq %r8,%xmm2\n\t"
6507 "movq %r9,%xmm3\n\t"
6509 "leaq -16(%rbp),%rsp\n\t"
6511 __ASM_CFI(".cfi_same_value %rdi\n\t")
6513 __ASM_CFI(".cfi_same_value %rsi\n\t")
6514 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6516 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6517 __ASM_CFI(".cfi_same_value %rbp\n\t")
6520 /* same function but returning floating point */
6521 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6523 #endif /* __x86_64__ */
6525 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6528 ITypeInfo
*tinfo2
= NULL
;
6529 TYPEATTR
*tattr
= NULL
;
6531 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6534 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6536 tdesc
->u
.hreftype
, hr
);
6539 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6542 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6543 ITypeInfo_Release(tinfo2
);
6547 switch (tattr
->typekind
)
6554 tdesc
= &tattr
->tdescAlias
;
6555 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6558 case TKIND_INTERFACE
:
6559 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6565 case TKIND_DISPATCH
:
6574 FIXME("TKIND_RECORD unhandled.\n");
6579 FIXME("TKIND_UNION unhandled.\n");
6584 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6588 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6589 ITypeInfo_Release(tinfo2
);
6593 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6597 /* enforce only one level of pointer indirection */
6598 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6600 tdesc
= tdesc
->u
.lptdesc
;
6602 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6603 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6604 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6605 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6606 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6608 VARTYPE vt_userdefined
= 0;
6609 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6610 if (tdesc
->vt
== VT_PTR
)
6612 vt_userdefined
= VT_BYREF
;
6613 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6615 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6617 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6618 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6620 *vt
|= vt_userdefined
;
6632 case VT_USERDEFINED
:
6633 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6640 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6641 hr
= DISP_E_BADVARTYPE
;
6645 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6660 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6666 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6670 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6672 ITypeInfo_Release(tinfo2
);
6676 switch(tattr
->typekind
) {
6678 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6681 case TKIND_INTERFACE
:
6682 case TKIND_DISPATCH
:
6683 *guid
= tattr
->guid
;
6687 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6688 hres
= E_UNEXPECTED
;
6691 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6692 ITypeInfo_Release(tinfo2
);
6696 /***********************************************************************
6697 * DispCallFunc (OLEAUT32.@)
6699 * Invokes a function of the specified calling convention, passing the
6700 * specified arguments and returns the result.
6703 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6704 * oVft [I] The offset in the vtable. See notes.
6705 * cc [I] Calling convention of the function to call.
6706 * vtReturn [I] The return type of the function.
6707 * cActuals [I] Number of parameters.
6708 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6709 * prgpvarg [I] The arguments to pass.
6710 * pvargResult [O] The return value of the function. Can be NULL.
6714 * Failure: HRESULT code.
6717 * The HRESULT return value of this function is not affected by the return
6718 * value of the user supplied function, which is returned in pvargResult.
6720 * If pvInstance is NULL then a non-object function is to be called and oVft
6721 * is the address of the function to call.
6723 * The cc parameter can be one of the following values:
6736 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6737 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6740 int argspos
, stack_offset
;
6745 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6746 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6747 pvargResult
, V_VT(pvargResult
));
6749 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6751 FIXME("unsupported calling convention %d\n",cc
);
6752 return E_INVALIDARG
;
6755 /* maximum size for an argument is sizeof(VARIANT) */
6756 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6758 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6762 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6763 func
= vtable
[oVft
/sizeof(void *)];
6764 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6766 else func
= (void *)oVft
;
6768 for (i
= 0; i
< cActuals
; i
++)
6770 VARIANT
*arg
= prgpvarg
[i
];
6781 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6782 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6786 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6787 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6789 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6790 args
[argspos
++] = V_BOOL(arg
);
6793 args
[argspos
++] = V_UI4(arg
);
6796 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6803 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6806 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6810 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6814 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6815 call_method( func
, argspos
, args
, &stack_offset
);
6820 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6823 WARN("invalid return type %u\n", vtReturn
);
6825 return E_INVALIDARG
;
6827 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6831 if (stack_offset
&& cc
== CC_STDCALL
)
6833 WARN( "stack pointer off by %d\n", stack_offset
);
6834 return DISP_E_BADCALLEE
;
6836 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6837 TRACE("retval: "); dump_Variant(pvargResult
);
6840 #elif defined(__x86_64__)
6846 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6847 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6848 pvargResult
, V_VT(pvargResult
));
6850 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6852 FIXME("unsupported calling convention %d\n",cc
);
6853 return E_INVALIDARG
;
6856 /* maximum size for an argument is sizeof(DWORD_PTR) */
6857 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6859 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6863 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6864 func
= vtable
[oVft
/sizeof(void *)];
6865 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6867 else func
= (void *)oVft
;
6869 for (i
= 0; i
< cActuals
; i
++)
6871 VARIANT
*arg
= prgpvarg
[i
];
6877 args
[argspos
++] = (ULONG_PTR
)arg
;
6879 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6880 args
[argspos
++] = V_BOOL(arg
);
6883 args
[argspos
++] = V_UI8(arg
);
6886 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6893 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6897 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6901 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6902 call_method( func
, argspos
, args
);
6905 WARN("invalid return type %u\n", vtReturn
);
6907 return E_INVALIDARG
;
6909 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6913 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6914 TRACE("retval: "); dump_Variant(pvargResult
);
6918 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6919 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6924 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6926 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6929 #define INVBUF_ELEMENT_SIZE \
6930 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6931 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6932 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6933 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6934 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6935 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6936 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6937 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6939 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6944 DISPPARAMS
*pDispParams
,
6945 VARIANT
*pVarResult
,
6946 EXCEPINFO
*pExcepInfo
,
6949 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6951 unsigned int var_index
;
6954 const TLBFuncDesc
*pFuncInfo
;
6957 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6958 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6961 if( This
->wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6962 return DISP_E_MEMBERNOTFOUND
;
6966 ERR("NULL pDispParams not allowed\n");
6967 return E_INVALIDARG
;
6970 dump_DispParms(pDispParams
);
6972 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6974 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6975 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6976 return E_INVALIDARG
;
6979 /* we do this instead of using GetFuncDesc since it will return a fake
6980 * FUNCDESC for dispinterfaces and we want the real function description */
6981 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
6982 pFuncInfo
= &This
->funcdescs
[fdc
];
6983 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6984 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6985 !func_restricted( &pFuncInfo
->funcdesc
))
6989 if (fdc
< This
->cFuncs
) {
6990 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6994 TRACE("invoking:\n");
6995 dump_TLBFuncDescOne(pFuncInfo
);
6998 switch (func_desc
->funckind
) {
6999 case FUNC_PUREVIRTUAL
:
7000 case FUNC_VIRTUAL
: {
7001 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7003 VARIANT retval
; /* pointer for storing byref retvals in */
7004 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7005 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7006 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7007 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7008 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7009 UINT vargs_converted
=0;
7013 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7015 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7017 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7018 hres
= DISP_E_PARAMNOTFOUND
;
7023 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7025 ERR("functions with the vararg attribute do not support named arguments\n");
7026 hres
= DISP_E_NONAMEDARGS
;
7030 for (i
= 0; i
< func_desc
->cParams
; i
++)
7032 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7033 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7038 TRACE("changing args\n");
7039 for (i
= 0; i
< func_desc
->cParams
; i
++)
7041 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7042 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7043 VARIANTARG
*src_arg
;
7045 if (wParamFlags
& PARAMFLAG_FLCID
)
7048 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7050 V_I4(arg
) = This
->pTypeLib
->lcid
;
7059 for (j
= 0; j
< cNamedArgs
; j
++)
7060 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7062 src_arg
= &pDispParams
->rgvarg
[j
];
7067 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7069 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7073 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7075 /* under most conditions the caller is not allowed to
7076 * pass in a dispparam arg in the index of what would be
7077 * the retval parameter. however, there is an exception
7078 * where the extra parameter is used in an extra
7079 * IDispatch::Invoke below */
7080 if ((i
< pDispParams
->cArgs
) &&
7081 ((func_desc
->cParams
!= 1) || !pVarResult
||
7082 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7084 hres
= DISP_E_BADPARAMCOUNT
;
7088 /* note: this check is placed so that if the caller passes
7089 * in a VARIANTARG for the retval we just ignore it, like
7091 if (i
== func_desc
->cParams
- 1)
7094 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7095 memset(arg
, 0, sizeof(*arg
));
7096 V_VT(arg
) = rgvt
[i
];
7097 memset(&retval
, 0, sizeof(retval
));
7098 V_BYREF(arg
) = &retval
;
7102 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7103 hres
= E_UNEXPECTED
;
7109 dump_Variant(src_arg
);
7111 if(rgvt
[i
]!=V_VT(src_arg
))
7113 if (rgvt
[i
] == VT_VARIANT
)
7114 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7115 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7117 if (rgvt
[i
] == V_VT(src_arg
))
7118 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7121 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7122 if (wParamFlags
& PARAMFLAG_FIN
)
7123 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7124 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7126 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7128 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
7131 SAFEARRAYBOUND bound
;
7135 bound
.cElements
= pDispParams
->cArgs
-i
;
7136 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7138 ERR("SafeArrayCreate failed\n");
7141 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7144 ERR("SafeArrayAccessData failed with %x\n", hres
);
7145 SafeArrayDestroy(a
);
7148 for (j
= 0; j
< bound
.cElements
; j
++)
7149 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7150 hres
= SafeArrayUnaccessData(a
);
7153 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7154 SafeArrayDestroy(a
);
7157 V_ARRAY(&rgvarg
[i
]) = a
;
7158 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7160 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7162 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7163 if (wParamFlags
& PARAMFLAG_FIN
)
7164 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7166 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7167 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7168 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7170 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7172 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7173 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7177 /* FIXME: this doesn't work for VT_BYREF arguments if
7178 * they are not the same type as in the paramdesc */
7179 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7180 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7181 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7186 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
7187 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
7188 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
7191 prgpvarg
[i
] = &rgvarg
[i
];
7195 prgpvarg
[i
] = src_arg
;
7198 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7199 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7200 && V_UNKNOWN(prgpvarg
[i
])) {
7201 IUnknown
*userdefined_iface
;
7204 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7208 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7210 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7214 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7215 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7218 else if (wParamFlags
& PARAMFLAG_FOPT
)
7221 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7222 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7224 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7230 VARIANTARG
*missing_arg
;
7231 /* if the function wants a pointer to a variant then
7232 * set that up, otherwise just pass the VT_ERROR in
7233 * the argument by value */
7234 if (rgvt
[i
] & VT_BYREF
)
7236 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7237 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7238 V_VARIANTREF(arg
) = missing_arg
;
7242 V_VT(missing_arg
) = VT_ERROR
;
7243 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7248 hres
= DISP_E_BADPARAMCOUNT
;
7252 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7254 /* VT_VOID is a special case for return types, so it is not
7255 * handled in the general function */
7256 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7257 V_VT(&varresult
) = VT_EMPTY
;
7260 V_VT(&varresult
) = 0;
7261 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7262 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7265 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7266 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7267 prgpvarg
, &varresult
);
7269 vargs_converted
= 0;
7271 for (i
= 0; i
< func_desc
->cParams
; i
++)
7273 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7274 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7276 if (wParamFlags
& PARAMFLAG_FLCID
)
7278 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7282 TRACE("[retval] value: ");
7283 dump_Variant(prgpvarg
[i
]);
7288 VariantInit(pVarResult
);
7289 /* deref return value */
7290 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7293 VARIANT_ClearInd(prgpvarg
[i
]);
7295 else if (vargs_converted
< pDispParams
->cArgs
)
7297 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7298 if (wParamFlags
& PARAMFLAG_FOUT
)
7300 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7302 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7306 ERR("failed to convert param %d to vt %d\n", i
,
7307 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7312 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7313 func_desc
->cParamsOpt
< 0 &&
7314 i
== func_desc
->cParams
-1)
7316 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7319 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7322 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7325 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7328 ERR("SafeArrayAccessData failed with %x\n", hres
);
7331 for (j
= 0; j
<= ubound
; j
++)
7332 VariantClear(&v
[j
]);
7333 hres
= SafeArrayUnaccessData(a
);
7336 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7340 VariantClear(&rgvarg
[i
]);
7343 else if (wParamFlags
& PARAMFLAG_FOPT
)
7345 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7346 VariantClear(&rgvarg
[i
]);
7349 VariantClear(&missing_arg
[i
]);
7352 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7354 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7355 hres
= DISP_E_EXCEPTION
;
7358 IErrorInfo
*pErrorInfo
;
7359 pExcepInfo
->scode
= V_ERROR(&varresult
);
7360 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7362 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7363 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7364 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7365 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7367 IErrorInfo_Release(pErrorInfo
);
7371 if (V_VT(&varresult
) != VT_ERROR
)
7373 TRACE("varresult value: ");
7374 dump_Variant(&varresult
);
7378 VariantClear(pVarResult
);
7379 *pVarResult
= varresult
;
7382 VariantClear(&varresult
);
7385 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7386 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7387 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7388 (pDispParams
->cArgs
!= 0))
7390 if (V_VT(pVarResult
) == VT_DISPATCH
)
7392 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7393 /* Note: not VariantClear; we still need the dispatch
7394 * pointer to be valid */
7395 VariantInit(pVarResult
);
7396 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7397 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7398 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7399 IDispatch_Release(pDispatch
);
7403 VariantClear(pVarResult
);
7404 hres
= DISP_E_NOTACOLLECTION
;
7412 case FUNC_DISPATCH
: {
7415 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7416 if (SUCCEEDED(hres
)) {
7417 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7418 hres
= IDispatch_Invoke(
7419 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7420 pVarResult
,pExcepInfo
,pArgErr
7423 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7424 IDispatch_Release(disp
);
7426 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7430 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7435 TRACE("-- 0x%08x\n", hres
);
7438 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7441 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7442 if(FAILED(hres
)) return hres
;
7444 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7445 dump_VARDESC(var_desc
);
7446 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7450 /* not found, look for it in inherited interfaces */
7451 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7452 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7453 if(This
->impltypes
) {
7454 /* recursive search */
7456 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7457 if(SUCCEEDED(hres
)){
7458 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7459 ITypeInfo_Release(pTInfo
);
7462 WARN("Could not search inherited interface!\n");
7465 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7466 return DISP_E_MEMBERNOTFOUND
;
7469 /* ITypeInfo::GetDocumentation
7471 * Retrieves the documentation string, the complete Help file name and path,
7472 * and the context ID for the Help topic for a specified type description.
7474 * (Can be tested by the Visual Basic Editor in Word for instance.)
7476 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7477 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7478 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7480 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7481 const TLBFuncDesc
*pFDesc
;
7482 const TLBVarDesc
*pVDesc
;
7483 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7484 " HelpContext(%p) HelpFile(%p)\n",
7485 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7486 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7488 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7490 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7492 *pdwHelpContext
=This
->dwHelpContext
;
7494 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7496 }else {/* for a member */
7497 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7500 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7502 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7504 *pdwHelpContext
=pFDesc
->helpcontext
;
7506 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7509 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7512 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7514 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7516 *pdwHelpContext
=pVDesc
->HelpContext
;
7518 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7523 if(This
->impltypes
&&
7524 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
7525 /* recursive search */
7528 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7529 if(SUCCEEDED(result
)) {
7530 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7531 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7532 ITypeInfo_Release(pTInfo
);
7535 WARN("Could not search inherited interface!\n");
7538 WARN("member %d not found\n", memid
);
7539 return TYPE_E_ELEMENTNOTFOUND
;
7542 /* ITypeInfo::GetDllEntry
7544 * Retrieves a description or specification of an entry point for a function
7547 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7548 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7551 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7552 const TLBFuncDesc
*pFDesc
;
7554 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7556 if (pBstrDllName
) *pBstrDllName
= NULL
;
7557 if (pBstrName
) *pBstrName
= NULL
;
7558 if (pwOrdinal
) *pwOrdinal
= 0;
7560 if (This
->typekind
!= TKIND_MODULE
)
7561 return TYPE_E_BADMODULEKIND
;
7563 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7565 dump_TypeInfo(This
);
7567 dump_TLBFuncDescOne(pFDesc
);
7570 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7572 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7574 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7582 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7585 return TYPE_E_ELEMENTNOTFOUND
;
7588 /* internal function to make the inherited interfaces' methods appear
7589 * part of the interface */
7590 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7591 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7593 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7596 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7598 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7600 ITypeInfo
*pSubTypeInfo
;
7602 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7606 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7608 ITypeInfo_Release(pSubTypeInfo
);
7612 *hRefType
-= DISPATCH_HREF_OFFSET
;
7614 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7615 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7620 /* ITypeInfo::GetRefTypeInfo
7622 * If a type description references other type descriptions, it retrieves
7623 * the referenced type descriptions.
7625 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7628 ITypeInfo
**ppTInfo
)
7630 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7631 HRESULT result
= E_FAIL
;
7634 return E_INVALIDARG
;
7636 if ((INT
)hRefType
< 0) {
7637 ITypeInfoImpl
*pTypeInfoImpl
;
7639 if (!(This
->wTypeFlags
& TYPEFLAG_FDUAL
) ||
7640 !(This
->typekind
== TKIND_INTERFACE
||
7641 This
->typekind
== TKIND_DISPATCH
))
7642 return TYPE_E_ELEMENTNOTFOUND
;
7644 /* when we meet a DUAL typeinfo, we must create the alternate
7647 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7649 *pTypeInfoImpl
= *This
;
7650 pTypeInfoImpl
->ref
= 0;
7651 list_init(&pTypeInfoImpl
->custdata_list
);
7653 if (This
->typekind
== TKIND_INTERFACE
)
7654 pTypeInfoImpl
->typekind
= TKIND_DISPATCH
;
7656 pTypeInfoImpl
->typekind
= TKIND_INTERFACE
;
7658 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7659 /* the AddRef implicitly adds a reference to the parent typelib, which
7660 * stops the copied data from being destroyed until the new typeinfo's
7661 * refcount goes to zero, but we need to signal to the new instance to
7662 * not free its data structures when it is destroyed */
7663 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7665 ITypeInfo_AddRef(*ppTInfo
);
7668 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7669 (This
->typekind
== TKIND_DISPATCH
))
7671 HREFTYPE href_dispatch
= hRefType
;
7672 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7674 TLBRefType
*ref_type
;
7675 ITypeLib
*pTLib
= NULL
;
7678 if(!(hRefType
& 0x1)){
7679 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7681 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7684 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7685 ITypeInfo_AddRef(*ppTInfo
);
7691 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7693 if(ref_type
->reference
== (hRefType
& (~0x3)))
7696 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7698 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7702 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7704 TRACE("internal reference\n");
7705 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7707 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7708 TRACE("typeinfo in imported typelib that is already loaded\n");
7709 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7710 ITypeLib_AddRef(pTLib
);
7715 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7717 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7718 ref_type
->pImpTLInfo
->wVersionMajor
,
7719 ref_type
->pImpTLInfo
->wVersionMinor
,
7720 This
->pTypeLib
->syskind
,
7721 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7723 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7725 result
= LoadTypeLib(libnam
, &pTLib
);
7726 SysFreeString(libnam
);
7728 if(SUCCEEDED(result
)) {
7729 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7730 ITypeLib_AddRef(pTLib
);
7734 if(SUCCEEDED(result
)) {
7735 if(ref_type
->index
== TLB_REF_USE_GUID
)
7736 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7738 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7741 ITypeLib_Release(pTLib
);
7745 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7746 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7750 /* ITypeInfo::AddressOfMember
7752 * Retrieves the addresses of static functions or variables, such as those
7755 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7756 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7758 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7764 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7766 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7770 module
= LoadLibraryW(dll
);
7773 ERR("couldn't load %s\n", debugstr_w(dll
));
7775 SysFreeString(entry
);
7776 return STG_E_FILENOTFOUND
;
7778 /* FIXME: store library somewhere where we can free it */
7783 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7784 entryA
= heap_alloc(len
);
7785 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7787 *ppv
= GetProcAddress(module
, entryA
);
7789 ERR("function not found %s\n", debugstr_a(entryA
));
7795 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7797 ERR("function not found %d\n", ordinal
);
7801 SysFreeString(entry
);
7804 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7809 /* ITypeInfo::CreateInstance
7811 * Creates a new instance of a type that describes a component object class
7814 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7815 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7817 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7821 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7827 WARN("Not able to aggregate\n");
7828 return CLASS_E_NOAGGREGATION
;
7831 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7832 if(FAILED(hr
)) return hr
;
7834 if(pTA
->typekind
!= TKIND_COCLASS
)
7836 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7842 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7845 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7846 TRACE("GetActiveObject rets %08x\n", hr
);
7849 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7850 IUnknown_Release(pUnk
);
7855 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7856 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7860 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7864 /* ITypeInfo::GetMops
7866 * Retrieves marshalling information.
7868 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7871 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7872 FIXME("(%p %d) stub!\n", This
, memid
);
7877 /* ITypeInfo::GetContainingTypeLib
7879 * Retrieves the containing type library and the index of the type description
7880 * within that type library.
7882 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7883 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7885 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7887 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7889 *pIndex
=This
->index
;
7890 TRACE("returning pIndex=%d\n", *pIndex
);
7894 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7895 ITypeLib_AddRef(*ppTLib
);
7896 TRACE("returning ppTLib=%p\n", *ppTLib
);
7902 /* ITypeInfo::ReleaseTypeAttr
7904 * Releases a TYPEATTR previously returned by Get
7907 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7908 TYPEATTR
* pTypeAttr
)
7910 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7911 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7912 heap_free(pTypeAttr
);
7915 /* ITypeInfo::ReleaseFuncDesc
7917 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7919 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7921 FUNCDESC
*pFuncDesc
)
7923 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7926 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7928 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7929 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7930 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7932 SysFreeString((BSTR
)pFuncDesc
);
7935 /* ITypeInfo::ReleaseVarDesc
7937 * Releases a VARDESC previously returned by GetVarDesc.
7939 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7942 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7943 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7945 TLB_FreeVarDesc(pVarDesc
);
7948 /* ITypeInfo2::GetTypeKind
7950 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7953 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7954 TYPEKIND
*pTypeKind
)
7956 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7957 *pTypeKind
=This
->typekind
;
7958 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7962 /* ITypeInfo2::GetTypeFlags
7964 * Returns the type flags without any allocations. This returns a DWORD type
7965 * flag, which expands the type flags without growing the TYPEATTR (type
7969 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7971 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7972 *pTypeFlags
=This
->wTypeFlags
;
7973 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7977 /* ITypeInfo2::GetFuncIndexOfMemId
7978 * Binds to a specific member based on a known DISPID, where the member name
7979 * is not known (for example, when binding to a default member).
7982 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7983 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7985 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7989 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
7990 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7991 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7994 if(fdc
< This
->cFuncs
) {
7998 result
= TYPE_E_ELEMENTNOTFOUND
;
8000 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
8001 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8005 /* TypeInfo2::GetVarIndexOfMemId
8007 * Binds to a specific member based on a known DISPID, where the member name
8008 * is not known (for example, when binding to a default member).
8011 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8012 MEMBERID memid
, UINT
*pVarIndex
)
8014 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8015 TLBVarDesc
*pVarInfo
;
8017 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8019 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8021 return TYPE_E_ELEMENTNOTFOUND
;
8023 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8028 /* ITypeInfo2::GetCustData
8030 * Gets the custom data
8032 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8037 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8038 TLBCustData
*pCData
;
8040 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8042 if(!guid
|| !pVarVal
)
8043 return E_INVALIDARG
;
8045 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8047 VariantInit( pVarVal
);
8049 VariantCopy( pVarVal
, &pCData
->data
);
8051 VariantClear( pVarVal
);
8055 /* ITypeInfo2::GetFuncCustData
8057 * Gets the custom data
8059 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8065 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8066 TLBCustData
*pCData
;
8067 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8069 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8071 if(index
>= This
->cFuncs
)
8072 return TYPE_E_ELEMENTNOTFOUND
;
8074 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8076 return TYPE_E_ELEMENTNOTFOUND
;
8078 VariantInit(pVarVal
);
8079 VariantCopy(pVarVal
, &pCData
->data
);
8084 /* ITypeInfo2::GetParamCustData
8086 * Gets the custom data
8088 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8095 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8096 TLBCustData
*pCData
;
8097 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8099 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8100 debugstr_guid(guid
), pVarVal
);
8102 if(indexFunc
>= This
->cFuncs
)
8103 return TYPE_E_ELEMENTNOTFOUND
;
8105 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8106 return TYPE_E_ELEMENTNOTFOUND
;
8108 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8110 return TYPE_E_ELEMENTNOTFOUND
;
8112 VariantInit(pVarVal
);
8113 VariantCopy(pVarVal
, &pCData
->data
);
8118 /* ITypeInfo2::GetVarCustData
8120 * Gets the custom data
8122 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8128 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8129 TLBCustData
*pCData
;
8130 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8132 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8134 if(index
>= This
->cVars
)
8135 return TYPE_E_ELEMENTNOTFOUND
;
8137 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8139 return TYPE_E_ELEMENTNOTFOUND
;
8141 VariantInit(pVarVal
);
8142 VariantCopy(pVarVal
, &pCData
->data
);
8147 /* ITypeInfo2::GetImplCustData
8149 * Gets the custom data
8151 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8157 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8158 TLBCustData
*pCData
;
8159 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8161 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8163 if(index
>= This
->cImplTypes
)
8164 return TYPE_E_ELEMENTNOTFOUND
;
8166 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8168 return TYPE_E_ELEMENTNOTFOUND
;
8170 VariantInit(pVarVal
);
8171 VariantCopy(pVarVal
, &pCData
->data
);
8176 /* ITypeInfo2::GetDocumentation2
8178 * Retrieves the documentation string, the complete Help file name and path,
8179 * the localization context to use, and the context ID for the library Help
8180 * topic in the Help file.
8183 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8187 BSTR
*pbstrHelpString
,
8188 DWORD
*pdwHelpStringContext
,
8189 BSTR
*pbstrHelpStringDll
)
8191 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8192 const TLBFuncDesc
*pFDesc
;
8193 const TLBVarDesc
*pVDesc
;
8194 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8195 "HelpStringContext(%p) HelpStringDll(%p)\n",
8196 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8197 pbstrHelpStringDll
);
8198 /* the help string should be obtained from the helpstringdll,
8199 * using the _DLLGetDocumentation function, based on the supplied
8200 * lcid. Nice to do sometime...
8202 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8204 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8205 if(pdwHelpStringContext
)
8206 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8207 if(pbstrHelpStringDll
)
8208 *pbstrHelpStringDll
=
8209 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8211 }else {/* for a member */
8212 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
8215 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8216 if(pdwHelpStringContext
)
8217 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8218 if(pbstrHelpStringDll
)
8219 *pbstrHelpStringDll
=
8220 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8223 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8226 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8227 if(pdwHelpStringContext
)
8228 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8229 if(pbstrHelpStringDll
)
8230 *pbstrHelpStringDll
=
8231 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8235 return TYPE_E_ELEMENTNOTFOUND
;
8238 /* ITypeInfo2::GetAllCustData
8240 * Gets all custom data items for the Type info.
8243 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8245 CUSTDATA
*pCustData
)
8247 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8249 TRACE("%p %p\n", This
, pCustData
);
8251 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8254 /* ITypeInfo2::GetAllFuncCustData
8256 * Gets all custom data items for the specified Function
8259 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8262 CUSTDATA
*pCustData
)
8264 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8265 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8267 TRACE("%p %u %p\n", This
, index
, pCustData
);
8269 if(index
>= This
->cFuncs
)
8270 return TYPE_E_ELEMENTNOTFOUND
;
8272 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8275 /* ITypeInfo2::GetAllParamCustData
8277 * Gets all custom data items for the Functions
8280 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8281 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8283 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8284 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8286 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8288 if(indexFunc
>= This
->cFuncs
)
8289 return TYPE_E_ELEMENTNOTFOUND
;
8291 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8292 return TYPE_E_ELEMENTNOTFOUND
;
8294 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8297 /* ITypeInfo2::GetAllVarCustData
8299 * Gets all custom data items for the specified Variable
8302 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8303 UINT index
, CUSTDATA
*pCustData
)
8305 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8306 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8308 TRACE("%p %u %p\n", This
, index
, pCustData
);
8310 if(index
>= This
->cVars
)
8311 return TYPE_E_ELEMENTNOTFOUND
;
8313 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8316 /* ITypeInfo2::GetAllImplCustData
8318 * Gets all custom data items for the specified implementation type
8321 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8324 CUSTDATA
*pCustData
)
8326 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8327 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8329 TRACE("%p %u %p\n", This
, index
, pCustData
);
8331 if(index
>= This
->cImplTypes
)
8332 return TYPE_E_ELEMENTNOTFOUND
;
8334 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8337 static const ITypeInfo2Vtbl tinfvt
=
8340 ITypeInfo_fnQueryInterface
,
8342 ITypeInfo_fnRelease
,
8344 ITypeInfo_fnGetTypeAttr
,
8345 ITypeInfo_fnGetTypeComp
,
8346 ITypeInfo_fnGetFuncDesc
,
8347 ITypeInfo_fnGetVarDesc
,
8348 ITypeInfo_fnGetNames
,
8349 ITypeInfo_fnGetRefTypeOfImplType
,
8350 ITypeInfo_fnGetImplTypeFlags
,
8351 ITypeInfo_fnGetIDsOfNames
,
8353 ITypeInfo_fnGetDocumentation
,
8354 ITypeInfo_fnGetDllEntry
,
8355 ITypeInfo_fnGetRefTypeInfo
,
8356 ITypeInfo_fnAddressOfMember
,
8357 ITypeInfo_fnCreateInstance
,
8358 ITypeInfo_fnGetMops
,
8359 ITypeInfo_fnGetContainingTypeLib
,
8360 ITypeInfo_fnReleaseTypeAttr
,
8361 ITypeInfo_fnReleaseFuncDesc
,
8362 ITypeInfo_fnReleaseVarDesc
,
8364 ITypeInfo2_fnGetTypeKind
,
8365 ITypeInfo2_fnGetTypeFlags
,
8366 ITypeInfo2_fnGetFuncIndexOfMemId
,
8367 ITypeInfo2_fnGetVarIndexOfMemId
,
8368 ITypeInfo2_fnGetCustData
,
8369 ITypeInfo2_fnGetFuncCustData
,
8370 ITypeInfo2_fnGetParamCustData
,
8371 ITypeInfo2_fnGetVarCustData
,
8372 ITypeInfo2_fnGetImplTypeCustData
,
8373 ITypeInfo2_fnGetDocumentation2
,
8374 ITypeInfo2_fnGetAllCustData
,
8375 ITypeInfo2_fnGetAllFuncCustData
,
8376 ITypeInfo2_fnGetAllParamCustData
,
8377 ITypeInfo2_fnGetAllVarCustData
,
8378 ITypeInfo2_fnGetAllImplTypeCustData
,
8381 /******************************************************************************
8382 * CreateDispTypeInfo [OLEAUT32.31]
8384 * Build type information for an object so it can be called through an
8385 * IDispatch interface.
8388 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8389 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8392 * This call allows an objects methods to be accessed through IDispatch, by
8393 * building an ITypeInfo object that IDispatch can use to call through.
8395 HRESULT WINAPI
CreateDispTypeInfo(
8396 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8397 LCID lcid
, /* [I] Locale Id */
8398 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8400 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8401 ITypeLibImpl
*pTypeLibImpl
;
8402 unsigned int param
, func
;
8403 TLBFuncDesc
*pFuncDesc
;
8407 pTypeLibImpl
= TypeLibImpl_Constructor();
8408 if (!pTypeLibImpl
) return E_FAIL
;
8410 pTypeLibImpl
->TypeInfoCount
= 2;
8411 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8413 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8414 pTIIface
->pTypeLib
= pTypeLibImpl
;
8415 pTIIface
->index
= 0;
8416 pTIIface
->Name
= NULL
;
8417 pTIIface
->dwHelpContext
= -1;
8418 pTIIface
->guid
= NULL
;
8419 pTIIface
->lcid
= lcid
;
8420 pTIIface
->typekind
= TKIND_INTERFACE
;
8421 pTIIface
->wMajorVerNum
= 0;
8422 pTIIface
->wMinorVerNum
= 0;
8423 pTIIface
->cbAlignment
= 2;
8424 pTIIface
->cbSizeInstance
= -1;
8425 pTIIface
->cbSizeVft
= -1;
8426 pTIIface
->cFuncs
= 0;
8427 pTIIface
->cImplTypes
= 0;
8428 pTIIface
->cVars
= 0;
8429 pTIIface
->wTypeFlags
= 0;
8430 pTIIface
->hreftype
= 0;
8432 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8433 pFuncDesc
= pTIIface
->funcdescs
;
8434 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8435 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8436 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8437 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8438 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8439 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8440 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8441 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8442 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8443 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8444 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8445 pFuncDesc
->funcdesc
.cScodes
= 0;
8446 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8447 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8448 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8449 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8450 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8451 md
->cArgs
* sizeof(ELEMDESC
));
8452 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8453 for(param
= 0; param
< md
->cArgs
; param
++) {
8454 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8455 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8457 pFuncDesc
->helpcontext
= 0;
8458 pFuncDesc
->HelpStringContext
= 0;
8459 pFuncDesc
->HelpString
= NULL
;
8460 pFuncDesc
->Entry
= NULL
;
8461 list_init(&pFuncDesc
->custdata_list
);
8466 dump_TypeInfo(pTIIface
);
8468 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8469 pTIClass
->pTypeLib
= pTypeLibImpl
;
8470 pTIClass
->index
= 1;
8471 pTIClass
->Name
= NULL
;
8472 pTIClass
->dwHelpContext
= -1;
8473 pTIClass
->guid
= NULL
;
8474 pTIClass
->lcid
= lcid
;
8475 pTIClass
->typekind
= TKIND_COCLASS
;
8476 pTIClass
->wMajorVerNum
= 0;
8477 pTIClass
->wMinorVerNum
= 0;
8478 pTIClass
->cbAlignment
= 2;
8479 pTIClass
->cbSizeInstance
= -1;
8480 pTIClass
->cbSizeVft
= -1;
8481 pTIClass
->cFuncs
= 0;
8482 pTIClass
->cImplTypes
= 1;
8483 pTIClass
->cVars
= 0;
8484 pTIClass
->wTypeFlags
= 0;
8485 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8487 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8489 ref
= heap_alloc_zero(sizeof(*ref
));
8490 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8491 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8493 dump_TypeInfo(pTIClass
);
8495 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8497 ITypeInfo_AddRef(*pptinfo
);
8498 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8504 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8506 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8508 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8511 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8513 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8515 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8518 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8520 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8522 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8525 static HRESULT WINAPI
ITypeComp_fnBind(
8530 ITypeInfo
** ppTInfo
,
8531 DESCKIND
* pDescKind
,
8534 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8535 const TLBFuncDesc
*pFDesc
;
8536 const TLBVarDesc
*pVDesc
;
8537 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8540 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8542 *pDescKind
= DESCKIND_NONE
;
8543 pBindPtr
->lpfuncdesc
= NULL
;
8546 for(fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8547 pFDesc
= &This
->funcdescs
[fdc
];
8548 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8549 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8552 /* name found, but wrong flags */
8553 hr
= TYPE_E_TYPEMISMATCH
;
8557 if (fdc
< This
->cFuncs
)
8559 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8561 &pBindPtr
->lpfuncdesc
,
8562 This
->typekind
== TKIND_DISPATCH
);
8565 *pDescKind
= DESCKIND_FUNCDESC
;
8566 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8567 ITypeInfo_AddRef(*ppTInfo
);
8570 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, szName
);
8572 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8575 *pDescKind
= DESCKIND_VARDESC
;
8576 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8577 ITypeInfo_AddRef(*ppTInfo
);
8582 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8583 /* recursive search */
8587 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8590 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8591 ITypeInfo_Release(pTInfo
);
8595 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8596 ITypeComp_Release(pTComp
);
8597 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8598 This
->typekind
== TKIND_DISPATCH
)
8600 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8601 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8602 SysFreeString((BSTR
)tmp
);
8606 WARN("Could not search inherited interface!\n");
8608 if (hr
== DISP_E_MEMBERNOTFOUND
)
8610 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8614 static HRESULT WINAPI
ITypeComp_fnBindType(
8618 ITypeInfo
** ppTInfo
,
8619 ITypeComp
** ppTComp
)
8621 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8623 /* strange behaviour (does nothing) but like the
8626 if (!ppTInfo
|| !ppTComp
)
8635 static const ITypeCompVtbl tcompvt
=
8638 ITypeComp_fnQueryInterface
,
8640 ITypeComp_fnRelease
,
8643 ITypeComp_fnBindType
8646 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8647 ICreateTypeLib2
** ppctlib
)
8652 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8654 if (!szFile
) return E_INVALIDARG
;
8656 This
= TypeLibImpl_Constructor();
8658 return E_OUTOFMEMORY
;
8660 This
->lcid
= GetSystemDefaultLCID();
8661 This
->syskind
= syskind
;
8662 This
->ptr_size
= get_ptr_size(syskind
);
8664 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8666 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8667 return E_OUTOFMEMORY
;
8669 lstrcpyW(This
->path
, szFile
);
8671 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8672 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8676 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8677 REFIID riid
, void **object
)
8679 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8681 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8684 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8686 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8688 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8691 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8693 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8695 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8698 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8699 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8701 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8702 ITypeInfoImpl
*info
;
8705 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8707 if (!ctinfo
|| !name
)
8708 return E_INVALIDARG
;
8710 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8712 return TYPE_E_NAMECONFLICT
;
8714 if (This
->typeinfos
)
8715 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8716 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8718 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8720 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8722 info
->pTypeLib
= This
;
8723 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8724 info
->index
= This
->TypeInfoCount
;
8725 info
->typekind
= kind
;
8726 info
->cbAlignment
= 4;
8728 switch(info
->typekind
) {
8730 case TKIND_INTERFACE
:
8731 case TKIND_DISPATCH
:
8733 info
->cbSizeInstance
= This
->ptr_size
;
8737 info
->cbSizeInstance
= 0;
8740 info
->cbSizeInstance
= 2;
8743 info
->cbSizeInstance
= -0x75;
8746 FIXME("unrecognized typekind %d\n", info
->typekind
);
8747 info
->cbSizeInstance
= 0xdeadbeef;
8751 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8752 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8754 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8758 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8760 ++This
->TypeInfoCount
;
8765 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8768 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8770 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8773 return E_INVALIDARG
;
8775 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8780 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8781 WORD majorVerNum
, WORD minorVerNum
)
8783 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8785 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8787 This
->ver_major
= majorVerNum
;
8788 This
->ver_minor
= minorVerNum
;
8793 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8796 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8798 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8800 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8805 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8808 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8810 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8813 return E_INVALIDARG
;
8815 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8820 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8821 LPOLESTR helpFileName
)
8823 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8825 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8828 return E_INVALIDARG
;
8830 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8835 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8838 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8840 TRACE("%p %d\n", This
, helpContext
);
8842 This
->dwHelpContext
= helpContext
;
8847 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8850 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8852 TRACE("%p %x\n", This
, lcid
);
8854 This
->set_lcid
= lcid
;
8859 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8862 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8864 TRACE("%p %x\n", This
, libFlags
);
8866 This
->libflags
= libFlags
;
8871 typedef struct tagWMSFT_SegContents
{
8874 } WMSFT_SegContents
;
8876 typedef struct tagWMSFT_TLBFile
{
8878 WMSFT_SegContents typeinfo_seg
;
8879 WMSFT_SegContents impfile_seg
;
8880 WMSFT_SegContents impinfo_seg
;
8881 WMSFT_SegContents ref_seg
;
8882 WMSFT_SegContents guidhash_seg
;
8883 WMSFT_SegContents guid_seg
;
8884 WMSFT_SegContents namehash_seg
;
8885 WMSFT_SegContents name_seg
;
8886 WMSFT_SegContents string_seg
;
8887 WMSFT_SegContents typdesc_seg
;
8888 WMSFT_SegContents arraydesc_seg
;
8889 WMSFT_SegContents custdata_seg
;
8890 WMSFT_SegContents cdguids_seg
;
8892 WMSFT_SegContents aux_seg
;
8895 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8896 WMSFT_TLBFile
*file
)
8902 file
->string_seg
.len
= 0;
8903 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8906 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8908 return E_UNEXPECTED
;
8910 size
+= sizeof(INT16
);
8912 size
= (size
+ 4) & ~0x3;
8916 file
->string_seg
.len
+= size
;
8918 /* temporarily use str->offset to store the length of the aligned,
8919 * converted string */
8923 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8926 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8929 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8930 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8932 heap_free(file
->string_seg
.data
);
8933 return E_UNEXPECTED
;
8936 *((INT16
*)data
) = size
;
8938 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8942 str
->offset
= last_offs
;
8949 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8950 WMSFT_TLBFile
*file
)
8955 MSFT_NameIntro
*last_intro
= NULL
;
8957 file
->header
.nametablecount
= 0;
8958 file
->header
.nametablechars
= 0;
8960 file
->name_seg
.len
= 0;
8961 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8964 size
= strlenW(str
->str
);
8965 file
->header
.nametablechars
+= size
;
8966 file
->header
.nametablecount
++;
8968 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8970 return E_UNEXPECTED
;
8972 size
+= sizeof(MSFT_NameIntro
);
8974 size
= (size
+ 4) & ~0x3;
8978 file
->name_seg
.len
+= size
;
8980 /* temporarily use str->offset to store the length of the aligned,
8981 * converted string */
8985 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8986 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
8989 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8991 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8993 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8994 data
+ sizeof(MSFT_NameIntro
),
8995 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8997 heap_free(file
->name_seg
.data
);
8998 return E_UNEXPECTED
;
9000 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9002 intro
->hreftype
= -1; /* TODO? */
9003 intro
->namelen
= size
& 0xFF;
9004 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9005 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9006 intro
->namelen
|= hash
<< 16;
9007 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9008 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9010 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9011 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9013 /* update str->offset to actual value to use in other
9014 * compilation functions that require positions within
9015 * the string table */
9019 str
->offset
= last_offs
;
9024 last_intro
->hreftype
= 0; /* last one is 0? */
9029 static inline int hash_guid(GUID
*guid
)
9033 for (i
= 0; i
< 8; i
++)
9034 hash
^= ((const short *)guid
)[i
];
9039 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9042 MSFT_GuidEntry
*entry
;
9044 int hash_key
, *guidhashtab
;
9046 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9047 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9049 entry
= file
->guid_seg
.data
;
9051 guidhashtab
= file
->guidhash_seg
.data
;
9052 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9053 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9054 entry
->hreftype
= guid
->hreftype
;
9056 hash_key
= hash_guid(&guid
->guid
);
9057 entry
->next_hash
= guidhashtab
[hash_key
];
9058 guidhashtab
[hash_key
] = offs
;
9060 guid
->offset
= offs
;
9061 offs
+= sizeof(MSFT_GuidEntry
);
9068 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9071 VARTYPE arg_type
= V_VT(value
);
9074 DWORD ret
= file
->custdata_seg
.len
;
9076 if(arg_type
== VT_INT
)
9078 if(arg_type
== VT_UINT
)
9082 if(V_VT(value
) != arg_type
) {
9083 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9085 ERR("VariantChangeType failed: %08x\n", hres
);
9090 /* Check if default value can be stored in-place */
9095 if(V_UI4(&v
) > 0x3ffffff)
9108 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9111 /* have to allocate space in custdata_seg */
9120 /* Construct the data to be allocated */
9123 if(file
->custdata_seg
.data
){
9124 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9125 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9126 file
->custdata_seg
.len
+= sizeof(int) * 2;
9128 file
->custdata_seg
.len
= sizeof(int) * 2;
9129 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9132 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9133 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9135 /* TODO: Check if the encoded data is already present in custdata_seg */
9141 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9144 if(file
->custdata_seg
.data
){
9145 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9146 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9147 file
->custdata_seg
.len
+= len
;
9149 file
->custdata_seg
.len
= len
;
9150 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9153 *((unsigned short *)data
) = V_VT(value
);
9154 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9155 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9156 if(V_BSTR(&v
)[i
] <= 0x7f)
9157 data
[i
+6] = V_BSTR(&v
)[i
];
9161 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9162 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9165 /* TODO: Check if the encoded data is already present in custdata_seg */
9170 FIXME("Argument type not yet handled\n");
9175 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9177 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9179 DWORD offs
= file
->arraydesc_seg
.len
;
9183 /* TODO: we should check for duplicates, but that's harder because each
9184 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9185 * at the library-level) */
9187 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9188 if(!file
->arraydesc_seg
.data
)
9189 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9191 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9192 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
) + offs
;
9194 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9195 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9196 for(i
= 0; i
< desc
->cDims
; ++i
){
9197 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9198 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9204 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9210 VARTYPE vt
, subtype
;
9221 vt
= desc
->vt
& VT_TYPEMASK
;
9223 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9225 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9226 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9228 *out_size
+= 2 * sizeof(DWORD
);
9229 }else if(vt
== VT_CARRAY
){
9230 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9231 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9233 }else if(vt
== VT_USERDEFINED
){
9234 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9235 encoded
[1] = desc
->u
.hreftype
;
9236 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9238 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9256 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9259 data
= file
->typdesc_seg
.data
;
9260 while(offs
< file
->typdesc_seg
.len
){
9261 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9263 offs
+= sizeof(encoded
);
9266 file
->typdesc_seg
.len
+= sizeof(encoded
);
9267 if(!file
->typdesc_seg
.data
)
9268 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9270 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9272 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9277 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9279 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9280 DWORD ret
= cdguids_seg
->len
, offs
;
9281 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
9284 if(list_empty(custdata_list
))
9287 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9288 if(!cdguids_seg
->data
){
9289 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9291 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9293 offs
= ret
+ sizeof(MSFT_CDGuid
);
9294 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9295 cdguid
->GuidOffset
= cd
->guid
->offset
;
9296 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9297 cdguid
->next
= offs
;
9298 offs
+= sizeof(MSFT_CDGuid
);
9308 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9309 WMSFT_TLBFile
*file
)
9311 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9312 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9313 MSFT_VarRecord
*varrecord
;
9314 MSFT_FuncRecord
*funcrecord
;
9316 DWORD
*name
, *offsets
, offs
;
9318 for(i
= 0; i
< info
->cFuncs
; ++i
){
9319 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9321 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9323 /* optional fields */
9324 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9325 if(!list_empty(&desc
->custdata_list
))
9326 recorded_size
+= 7 * sizeof(INT
);
9327 else if(desc
->HelpStringContext
!= 0)
9328 recorded_size
+= 6 * sizeof(INT
);
9330 else if(desc
->Entry
)
9331 recorded_size
+= 3 * sizeof(INT
);
9332 else if(desc
->HelpString
)
9333 recorded_size
+= 2 * sizeof(INT
);
9334 else if(desc
->helpcontext
)
9335 recorded_size
+= sizeof(INT
);
9337 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9339 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9340 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9341 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9346 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9349 for(i
= 0; i
< info
->cVars
; ++i
){
9350 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9352 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9354 /* optional fields */
9355 if(desc
->HelpStringContext
!= 0)
9356 recorded_size
+= 5 * sizeof(INT
);
9357 else if(!list_empty(&desc
->custdata_list
))
9358 recorded_size
+= 4 * sizeof(INT
);
9360 else if(desc
->HelpString
)
9361 recorded_size
+= 2 * sizeof(INT
);
9362 else if(desc
->HelpContext
!= 0)
9363 recorded_size
+= sizeof(INT
);
9365 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9368 if(!recorded_size
&& !extra_size
)
9371 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9373 aux_seg
->len
+= recorded_size
+ extra_size
;
9375 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9378 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9380 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9382 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9384 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9387 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9388 for(i
= 0; i
< info
->cFuncs
; ++i
){
9389 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9390 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9392 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9393 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9394 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9395 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9398 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9403 * ^has_param_defaults
9404 * ^oEntry_is_intresource
9406 funcrecord
->FKCCIC
=
9407 desc
->funcdesc
.funckind
|
9408 (desc
->funcdesc
.invkind
<< 3) |
9409 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9410 (desc
->funcdesc
.callconv
<< 8);
9412 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9413 funcrecord
->FKCCIC
|= 0x2000;
9415 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9416 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9417 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9418 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9421 if(paramdefault_size
> 0)
9422 funcrecord
->FKCCIC
|= 0x1000;
9424 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9425 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9427 /* optional fields */
9429 if(!list_empty(&desc
->custdata_list
)){
9430 size
+= 7 * sizeof(INT
);
9431 funcrecord
->HelpContext
= desc
->helpcontext
;
9432 if(desc
->HelpString
)
9433 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9435 funcrecord
->oHelpString
= -1;
9437 funcrecord
->oEntry
= -1;
9438 else if(IS_INTRESOURCE(desc
->Entry
))
9439 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9441 funcrecord
->oEntry
= desc
->Entry
->offset
;
9442 funcrecord
->res9
= -1;
9443 funcrecord
->resA
= -1;
9444 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9445 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9446 }else if(desc
->HelpStringContext
!= 0){
9447 size
+= 6 * sizeof(INT
);
9448 funcrecord
->HelpContext
= desc
->helpcontext
;
9449 if(desc
->HelpString
)
9450 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9452 funcrecord
->oHelpString
= -1;
9454 funcrecord
->oEntry
= -1;
9455 else if(IS_INTRESOURCE(desc
->Entry
))
9456 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9458 funcrecord
->oEntry
= desc
->Entry
->offset
;
9459 funcrecord
->res9
= -1;
9460 funcrecord
->resA
= -1;
9461 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9462 }else if(desc
->Entry
){
9463 size
+= 3 * sizeof(INT
);
9464 funcrecord
->HelpContext
= desc
->helpcontext
;
9465 if(desc
->HelpString
)
9466 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9468 funcrecord
->oHelpString
= -1;
9470 funcrecord
->oEntry
= -1;
9471 else if(IS_INTRESOURCE(desc
->Entry
))
9472 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9474 funcrecord
->oEntry
= desc
->Entry
->offset
;
9475 }else if(desc
->HelpString
){
9476 size
+= 2 * sizeof(INT
);
9477 funcrecord
->HelpContext
= desc
->helpcontext
;
9478 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9479 }else if(desc
->helpcontext
){
9480 size
+= sizeof(INT
);
9481 funcrecord
->HelpContext
= desc
->helpcontext
;
9484 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9485 size
+= paramdefault_size
;
9487 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9488 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9490 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9491 if(desc
->pParamDesc
[j
].Name
)
9492 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9495 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9497 if(paramdefault_size
){
9498 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9499 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9500 else if(paramdefault_size
)
9505 size
+= sizeof(MSFT_ParameterInfo
);
9508 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9514 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9517 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9518 for(i
= 0; i
< info
->cVars
; ++i
){
9519 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9520 DWORD size
= 5 * sizeof(INT
);
9522 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9523 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9524 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9525 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9527 if(desc
->vardesc
.varkind
== VAR_CONST
){
9528 varrecord
->vardescsize
+= sizeof(VARIANT
);
9529 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9531 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9534 if(desc
->HelpStringContext
!= 0){
9535 size
+= 5 * sizeof(INT
);
9536 varrecord
->HelpContext
= desc
->HelpContext
;
9537 if(desc
->HelpString
)
9538 varrecord
->HelpString
= desc
->HelpString
->offset
;
9540 varrecord
->HelpString
= -1;
9541 varrecord
->res9
= -1;
9542 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9543 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9544 }else if(!list_empty(&desc
->custdata_list
)){
9545 size
+= 4 * sizeof(INT
);
9546 varrecord
->HelpContext
= desc
->HelpContext
;
9547 if(desc
->HelpString
)
9548 varrecord
->HelpString
= desc
->HelpString
->offset
;
9550 varrecord
->HelpString
= -1;
9551 varrecord
->res9
= -1;
9552 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9553 }else if(desc
->HelpString
){
9554 size
+= 2 * sizeof(INT
);
9555 varrecord
->HelpContext
= desc
->HelpContext
;
9556 if(desc
->HelpString
)
9557 varrecord
->HelpString
= desc
->HelpString
->offset
;
9559 varrecord
->HelpString
= -1;
9560 }else if(desc
->HelpContext
!= 0){
9561 size
+= sizeof(INT
);
9562 varrecord
->HelpContext
= desc
->HelpContext
;
9565 varrecord
->Info
= size
| (i
<< 16);
9571 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9574 memid
= (MEMBERID
*)varrecord
;
9575 for(i
= 0; i
< info
->cFuncs
; ++i
){
9576 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9577 *memid
= desc
->funcdesc
.memid
;
9580 for(i
= 0; i
< info
->cVars
; ++i
){
9581 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9582 *memid
= desc
->vardesc
.memid
;
9586 name
= (UINT
*)memid
;
9587 for(i
= 0; i
< info
->cFuncs
; ++i
){
9588 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9590 *name
= desc
->Name
->offset
;
9595 for(i
= 0; i
< info
->cVars
; ++i
){
9596 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9598 *name
= desc
->Name
->offset
;
9607 typedef struct tagWMSFT_RefChunk
{
9614 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9616 DWORD offs
= file
->ref_seg
.len
, i
;
9617 WMSFT_RefChunk
*chunk
;
9619 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9620 if(!file
->ref_seg
.data
)
9621 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9623 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9625 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9627 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9628 chunk
->href
= info
->impltypes
[i
].hRef
;
9629 chunk
->res04
= info
->impltypes
[i
].implflags
;
9631 if(i
< info
->cImplTypes
- 1)
9632 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9641 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9645 size
= sizeof(MSFT_TypeInfoBase
);
9648 MSFT_TypeInfoBase
*base
= (void*)data
;
9649 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9650 base
->typekind
= TKIND_DISPATCH
;
9652 base
->typekind
= info
->typekind
;
9653 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9654 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9655 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9660 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9666 base
->posguid
= info
->guid
->offset
;
9669 base
->flags
= info
->wTypeFlags
;
9671 base
->NameOffset
= info
->Name
->offset
;
9673 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9674 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9676 base
->NameOffset
= -1;
9678 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9680 base
->docstringoffs
= info
->DocString
->offset
;
9682 base
->docstringoffs
= -1;
9683 base
->helpstringcontext
= info
->dwHelpStringContext
;
9684 base
->helpcontext
= info
->dwHelpContext
;
9685 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9686 base
->cImplTypes
= info
->cImplTypes
;
9687 base
->cbSizeVft
= info
->cbSizeVft
;
9688 base
->size
= info
->cbSizeInstance
;
9689 if(info
->typekind
== TKIND_COCLASS
){
9690 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9691 }else if(info
->typekind
== TKIND_ALIAS
){
9692 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9693 }else if(info
->typekind
== TKIND_MODULE
){
9695 base
->datatype1
= info
->DllName
->offset
;
9697 base
->datatype1
= -1;
9699 if(info
->cImplTypes
> 0)
9700 base
->datatype1
= info
->impltypes
[0].hRef
;
9702 base
->datatype1
= -1;
9704 base
->datatype2
= index
; /* FIXME: i think there's more here */
9712 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9716 file
->typeinfo_seg
.len
= 0;
9717 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9718 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9719 *junk
= file
->typeinfo_seg
.len
;
9721 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9724 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9725 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9727 file
->aux_seg
.len
= 0;
9728 file
->aux_seg
.data
= NULL
;
9730 file
->typeinfo_seg
.len
= 0;
9731 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9732 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9733 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9734 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9738 typedef struct tagWMSFT_ImpFile
{
9744 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9747 WMSFT_ImpFile
*impfile
;
9749 DWORD last_offs
= 0;
9751 file
->impfile_seg
.len
= 0;
9752 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9756 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9760 path
= implib
->name
;
9761 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9763 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9766 size
+= sizeof(INT16
);
9768 size
= (size
+ 4) & ~0x3;
9772 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9775 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9777 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9778 int strlen
= 0, size
;
9780 impfile
= (WMSFT_ImpFile
*)data
;
9781 impfile
->guid_offs
= implib
->guid
->offset
;
9782 impfile
->lcid
= implib
->lcid
;
9783 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9785 data
+= sizeof(WMSFT_ImpFile
);
9788 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9792 path
= implib
->name
;
9793 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9794 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9796 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9799 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9801 size
= strlen
+ sizeof(INT16
);
9803 size
= (size
+ 4) & ~0x3;
9806 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9809 implib
->offset
= last_offs
;
9810 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9814 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9817 TLBRefType
*ref_type
;
9820 WMSFT_compile_impfile(This
, file
);
9822 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9823 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9825 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9826 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9827 if(ref_type
->index
== TLB_REF_USE_GUID
){
9828 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9829 info
->oGuid
= ref_type
->guid
->offset
;
9831 info
->oGuid
= ref_type
->index
;
9832 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9838 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9840 file
->guidhash_seg
.len
= 0x80;
9841 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9842 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9845 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9847 file
->namehash_seg
.len
= 0x200;
9848 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9849 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9852 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9854 if(contents
&& contents
->len
){
9855 segdir
->offset
= *running_offset
;
9856 segdir
->length
= contents
->len
;
9857 *running_offset
+= segdir
->length
;
9859 segdir
->offset
= -1;
9863 /* TODO: do these ever change? */
9865 segdir
->res0c
= 0xf;
9868 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9872 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9875 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9879 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9881 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9882 base
->memoffset
+= file_len
;
9889 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9891 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9892 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9893 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9894 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9895 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9896 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9897 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9898 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9899 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9900 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9901 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9902 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9903 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9904 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9907 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9909 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9911 DWORD written
, junk_size
, junk_offs
, running_offset
;
9918 TRACE("%p\n", This
);
9920 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
9921 if(This
->typeinfos
[i
]->needs_layout
)
9922 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
9924 memset(&file
, 0, sizeof(file
));
9926 file
.header
.magic1
= 0x5446534D;
9927 file
.header
.magic2
= 0x00010002;
9928 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9929 file
.header
.lcid2
= This
->set_lcid
;
9930 file
.header
.varflags
= 0x40 | This
->syskind
;
9932 file
.header
.varflags
|= 0x10;
9933 if (This
->HelpStringDll
)
9934 file
.header
.varflags
|= HELPDLLFLAG
;
9935 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
9936 file
.header
.flags
= This
->libflags
;
9937 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9938 file
.header
.helpcontext
= This
->dwHelpContext
;
9939 file
.header
.res44
= 0x20;
9940 file
.header
.res48
= 0x80;
9941 file
.header
.dispatchpos
= This
->dispatch_href
;
9943 WMSFT_compile_namehash(This
, &file
);
9944 /* do name and string compilation to get offsets for other compilations */
9945 hres
= WMSFT_compile_names(This
, &file
);
9947 WMSFT_free_file(&file
);
9951 hres
= WMSFT_compile_strings(This
, &file
);
9953 WMSFT_free_file(&file
);
9957 WMSFT_compile_guidhash(This
, &file
);
9958 hres
= WMSFT_compile_guids(This
, &file
);
9960 WMSFT_free_file(&file
);
9965 file
.header
.helpfile
= This
->HelpFile
->offset
;
9967 file
.header
.helpfile
= -1;
9970 file
.header
.helpstring
= This
->DocString
->offset
;
9972 file
.header
.helpstring
= -1;
9974 /* do some more segment compilation */
9975 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9976 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9979 file
.header
.NameOffset
= This
->Name
->offset
;
9981 file
.header
.NameOffset
= -1;
9983 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
9986 file
.header
.posguid
= This
->guid
->offset
;
9988 file
.header
.posguid
= -1;
9990 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9991 if(file
.header
.varflags
& HELPDLLFLAG
)
9992 junk_size
+= sizeof(DWORD
);
9994 junk
= heap_alloc_zero(junk_size
);
9995 if(file
.header
.varflags
& HELPDLLFLAG
){
9996 *junk
= This
->HelpStringDll
->offset
;
10005 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10006 WMSFT_compile_impinfo(This
, &file
);
10008 running_offset
= 0;
10010 TRACE("header at: 0x%x\n", running_offset
);
10011 running_offset
+= sizeof(file
.header
);
10013 TRACE("junk at: 0x%x\n", running_offset
);
10014 running_offset
+= junk_size
;
10016 TRACE("segdir at: 0x%x\n", running_offset
);
10017 running_offset
+= sizeof(file
.segdir
);
10019 TRACE("typeinfo at: 0x%x\n", running_offset
);
10020 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10022 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10023 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10025 TRACE("guidtab at: 0x%x\n", running_offset
);
10026 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10028 TRACE("reftab at: 0x%x\n", running_offset
);
10029 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10031 TRACE("impinfo at: 0x%x\n", running_offset
);
10032 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10034 TRACE("impfiles at: 0x%x\n", running_offset
);
10035 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10037 TRACE("namehashtab at: 0x%x\n", running_offset
);
10038 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10040 TRACE("nametab at: 0x%x\n", running_offset
);
10041 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10043 TRACE("stringtab at: 0x%x\n", running_offset
);
10044 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10046 TRACE("typdesc at: 0x%x\n", running_offset
);
10047 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10049 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10050 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10052 TRACE("custdata at: 0x%x\n", running_offset
);
10053 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10055 TRACE("cdguids at: 0x%x\n", running_offset
);
10056 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10058 TRACE("res0e at: 0x%x\n", running_offset
);
10059 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10061 TRACE("res0f at: 0x%x\n", running_offset
);
10062 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10064 TRACE("aux_seg at: 0x%x\n", running_offset
);
10066 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10068 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10069 FILE_ATTRIBUTE_NORMAL
, 0);
10070 if (outfile
== INVALID_HANDLE_VALUE
){
10071 WMSFT_free_file(&file
);
10073 return TYPE_E_IOERROR
;
10076 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10078 WMSFT_free_file(&file
);
10079 CloseHandle(outfile
);
10081 return TYPE_E_IOERROR
;
10084 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10087 WMSFT_free_file(&file
);
10088 CloseHandle(outfile
);
10089 return TYPE_E_IOERROR
;
10092 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10094 WMSFT_free_file(&file
);
10095 CloseHandle(outfile
);
10096 return TYPE_E_IOERROR
;
10099 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10100 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10101 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10102 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10103 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10104 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10105 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10106 WMSFT_write_segment(outfile
, &file
.name_seg
);
10107 WMSFT_write_segment(outfile
, &file
.string_seg
);
10108 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10109 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10110 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10111 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10112 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10114 WMSFT_free_file(&file
);
10116 CloseHandle(outfile
);
10121 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10124 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10125 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10129 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10130 REFGUID guid
, VARIANT
*varVal
)
10132 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10133 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
10137 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10138 ULONG helpStringContext
)
10140 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10141 FIXME("%p %u - stub\n", This
, helpStringContext
);
10145 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10148 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10149 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10152 return E_INVALIDARG
;
10154 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10159 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10160 ICreateTypeLib2_fnQueryInterface
,
10161 ICreateTypeLib2_fnAddRef
,
10162 ICreateTypeLib2_fnRelease
,
10163 ICreateTypeLib2_fnCreateTypeInfo
,
10164 ICreateTypeLib2_fnSetName
,
10165 ICreateTypeLib2_fnSetVersion
,
10166 ICreateTypeLib2_fnSetGuid
,
10167 ICreateTypeLib2_fnSetDocString
,
10168 ICreateTypeLib2_fnSetHelpFileName
,
10169 ICreateTypeLib2_fnSetHelpContext
,
10170 ICreateTypeLib2_fnSetLcid
,
10171 ICreateTypeLib2_fnSetLibFlags
,
10172 ICreateTypeLib2_fnSaveAllChanges
,
10173 ICreateTypeLib2_fnDeleteTypeInfo
,
10174 ICreateTypeLib2_fnSetCustData
,
10175 ICreateTypeLib2_fnSetHelpStringContext
,
10176 ICreateTypeLib2_fnSetHelpStringDll
10179 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10180 REFIID riid
, void **object
)
10182 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10184 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10187 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10189 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10191 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10194 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10196 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10198 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10201 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10204 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10206 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10208 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10213 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10216 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10220 TRACE("%p %x\n", This
, typeFlags
);
10222 if (typeFlags
& TYPEFLAG_FDUAL
) {
10223 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10225 ITypeInfo
*dispatch
;
10229 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10233 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10234 ITypeLib_Release(stdole
);
10238 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10239 ITypeInfo_Release(dispatch
);
10244 old_flags
= This
->wTypeFlags
;
10245 This
->wTypeFlags
= typeFlags
;
10247 hres
= ICreateTypeInfo2_LayOut(iface
);
10248 if (FAILED(hres
)) {
10249 This
->wTypeFlags
= old_flags
;
10256 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10259 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10261 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10264 return E_INVALIDARG
;
10266 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10271 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10274 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10276 TRACE("%p %d\n", This
, helpContext
);
10278 This
->dwHelpContext
= helpContext
;
10283 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10284 WORD majorVerNum
, WORD minorVerNum
)
10286 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10288 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10290 This
->wMajorVerNum
= majorVerNum
;
10291 This
->wMinorVerNum
= minorVerNum
;
10296 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10297 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10299 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10301 ITypeLib
*container
;
10302 TLBRefType
*ref_type
;
10304 TYPEATTR
*typeattr
;
10308 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10310 if (!typeInfo
|| !refType
)
10311 return E_INVALIDARG
;
10313 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10317 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10318 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10320 ITypeLib_Release(container
);
10322 *refType
= target
->hreftype
;
10327 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10328 if (FAILED(hres
)) {
10329 ITypeLib_Release(container
);
10333 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10334 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10335 implib
->lcid
== libattr
->lcid
&&
10336 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10337 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10341 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10342 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10344 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10345 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10346 implib
->name
= SysAllocString(our_container
->path
);
10348 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10349 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10351 implib
->name
= NULL
;
10352 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10356 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10357 implib
->lcid
= libattr
->lcid
;
10358 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10359 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10361 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10364 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10365 ITypeLib_Release(container
);
10367 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10372 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10373 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10374 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10375 ref_type
->tkind
== typeattr
->typekind
)
10380 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10381 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10383 ref_type
->tkind
= typeattr
->typekind
;
10384 ref_type
->pImpTLInfo
= implib
;
10385 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10387 ref_type
->index
= TLB_REF_USE_GUID
;
10389 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10391 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10394 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10396 *refType
= ref_type
->reference
| 0x1;
10398 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10399 This
->pTypeLib
->dispatch_href
= *refType
;
10404 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10405 UINT index
, FUNCDESC
*funcDesc
)
10407 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10408 TLBFuncDesc tmp_func_desc
, *func_desc
;
10413 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10415 if (!funcDesc
|| funcDesc
->oVft
& 3)
10416 return E_INVALIDARG
;
10418 switch (This
->typekind
) {
10420 if (funcDesc
->funckind
!= FUNC_STATIC
)
10421 return TYPE_E_BADMODULEKIND
;
10423 case TKIND_DISPATCH
:
10424 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10425 return TYPE_E_BADMODULEKIND
;
10428 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10429 return TYPE_E_BADMODULEKIND
;
10432 if (index
> This
->cFuncs
)
10433 return TYPE_E_ELEMENTNOTFOUND
;
10435 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10436 !funcDesc
->cParams
)
10437 return TYPE_E_INCONSISTENTPROPFUNCS
;
10440 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10441 funcDesc
->oVft
% 8 != 0)
10442 return E_INVALIDARG
;
10445 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10446 TLBFuncDesc_Constructor(&tmp_func_desc
);
10448 tmp_func_desc
.funcdesc
= *funcDesc
;
10450 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10451 tmp_func_desc
.funcdesc
.oVft
|= 1;
10453 if (funcDesc
->cScodes
) {
10454 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10455 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10457 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10459 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10460 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10461 buf_size
+= sizeof(ELEMDESC
);
10462 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10464 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10465 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10467 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10468 if (FAILED(hres
)) {
10469 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10470 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10474 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10475 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10476 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10477 if (FAILED(hres
)) {
10478 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10479 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10482 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10483 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10484 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10485 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10486 if (FAILED(hres
)) {
10487 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10488 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10494 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10496 if (This
->funcdescs
) {
10497 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10498 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10500 if (index
< This
->cFuncs
) {
10501 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10502 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10503 func_desc
= This
->funcdescs
+ index
;
10505 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10507 /* move custdata lists to the new memory location */
10508 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10510 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10511 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10512 list_init(&fd
->custdata_list
);
10514 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10515 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10520 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10522 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10523 list_init(&func_desc
->custdata_list
);
10527 This
->needs_layout
= TRUE
;
10532 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10533 UINT index
, HREFTYPE refType
)
10535 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10536 TLBImplType
*impl_type
;
10539 TRACE("%p %u %d\n", This
, index
, refType
);
10541 switch(This
->typekind
){
10542 case TKIND_COCLASS
: {
10544 FIXME("Unhandled index: -1\n");
10548 if(index
!= This
->cImplTypes
)
10549 return TYPE_E_ELEMENTNOTFOUND
;
10553 case TKIND_INTERFACE
:
10554 case TKIND_DISPATCH
:
10555 if (index
!= 0 || This
->cImplTypes
)
10556 return TYPE_E_ELEMENTNOTFOUND
;
10559 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10563 if (This
->impltypes
){
10566 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10567 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10569 if (index
< This
->cImplTypes
) {
10570 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10571 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10572 impl_type
= This
->impltypes
+ index
;
10574 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10576 /* move custdata lists to the new memory location */
10577 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10579 TLBImplType
*it
= &This
->impltypes
[i
];
10580 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10581 list_init(&it
->custdata_list
);
10583 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10584 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10589 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10591 memset(impl_type
, 0, sizeof(TLBImplType
));
10592 TLBImplType_Constructor(impl_type
);
10593 impl_type
->hRef
= refType
;
10595 ++This
->cImplTypes
;
10597 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10598 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10600 hres
= ICreateTypeInfo2_LayOut(iface
);
10607 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10608 UINT index
, INT implTypeFlags
)
10610 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10611 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10613 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10615 if (This
->typekind
!= TKIND_COCLASS
)
10616 return TYPE_E_BADMODULEKIND
;
10618 if (index
>= This
->cImplTypes
)
10619 return TYPE_E_ELEMENTNOTFOUND
;
10621 impl_type
->implflags
= implTypeFlags
;
10626 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10629 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10631 TRACE("%p %d\n", This
, alignment
);
10633 This
->cbAlignment
= alignment
;
10638 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10641 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10643 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10646 return E_INVALIDARG
;
10648 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10650 This
->lpstrSchema
= This
->Schema
->str
;
10655 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10656 UINT index
, VARDESC
*varDesc
)
10658 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10659 TLBVarDesc
*var_desc
;
10661 TRACE("%p %u %p\n", This
, index
, varDesc
);
10663 if (This
->vardescs
){
10666 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10667 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10669 if (index
< This
->cVars
) {
10670 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10671 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10672 var_desc
= This
->vardescs
+ index
;
10674 var_desc
= This
->vardescs
+ This
->cVars
;
10676 /* move custdata lists to the new memory location */
10677 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10679 TLBVarDesc
*var
= &This
->vardescs
[i
];
10680 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10681 list_init(&var
->custdata_list
);
10683 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10684 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10689 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10691 TLBVarDesc_Constructor(var_desc
);
10692 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10693 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10697 This
->needs_layout
= TRUE
;
10702 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10703 UINT index
, LPOLESTR
*names
, UINT numNames
)
10705 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10706 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10709 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10712 return E_INVALIDARG
;
10714 if (index
>= This
->cFuncs
|| numNames
== 0)
10715 return TYPE_E_ELEMENTNOTFOUND
;
10717 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10718 if(numNames
> func_desc
->funcdesc
.cParams
)
10719 return TYPE_E_ELEMENTNOTFOUND
;
10721 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10722 return TYPE_E_ELEMENTNOTFOUND
;
10724 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10725 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10726 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10727 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10728 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10729 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10731 return TYPE_E_AMBIGUOUSNAME
;
10735 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10737 for (i
= 1; i
< numNames
; ++i
) {
10738 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10739 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10745 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10746 UINT index
, LPOLESTR name
)
10748 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10750 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10753 return E_INVALIDARG
;
10755 if(index
>= This
->cVars
)
10756 return TYPE_E_ELEMENTNOTFOUND
;
10758 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10762 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10763 TYPEDESC
*tdescAlias
)
10765 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10768 TRACE("%p %p\n", This
, tdescAlias
);
10771 return E_INVALIDARG
;
10773 if(This
->typekind
!= TKIND_ALIAS
)
10774 return TYPE_E_BADMODULEKIND
;
10776 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->cbSizeInstance
, &This
->cbAlignment
);
10780 heap_free(This
->tdescAlias
);
10781 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10782 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10787 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10788 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10790 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10791 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10795 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10796 UINT index
, LPOLESTR docString
)
10798 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10799 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10801 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10804 return E_INVALIDARG
;
10806 if(index
>= This
->cFuncs
)
10807 return TYPE_E_ELEMENTNOTFOUND
;
10809 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10814 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10815 UINT index
, LPOLESTR docString
)
10817 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10818 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10820 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10823 return E_INVALIDARG
;
10825 if(index
>= This
->cVars
)
10826 return TYPE_E_ELEMENTNOTFOUND
;
10828 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10833 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10834 UINT index
, DWORD helpContext
)
10836 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10837 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10839 TRACE("%p %u %d\n", This
, index
, helpContext
);
10841 if(index
>= This
->cFuncs
)
10842 return TYPE_E_ELEMENTNOTFOUND
;
10844 func_desc
->helpcontext
= helpContext
;
10849 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10850 UINT index
, DWORD helpContext
)
10852 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10853 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10855 TRACE("%p %u %d\n", This
, index
, helpContext
);
10857 if(index
>= This
->cVars
)
10858 return TYPE_E_ELEMENTNOTFOUND
;
10860 var_desc
->HelpContext
= helpContext
;
10865 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10866 UINT index
, BSTR bstrMops
)
10868 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10869 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10873 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10876 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10878 TRACE("%p %p\n", This
, idlDesc
);
10881 return E_INVALIDARG
;
10883 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10884 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10889 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10891 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10893 TLBFuncDesc
*func_desc
;
10894 UINT user_vft
= 0, i
, depth
= 0;
10895 HRESULT hres
= S_OK
;
10897 TRACE("%p\n", This
);
10899 This
->needs_layout
= FALSE
;
10901 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10905 if (This
->typekind
== TKIND_INTERFACE
) {
10910 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10912 if (SUCCEEDED(hres
)) {
10913 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10915 if (SUCCEEDED(hres
)) {
10916 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10917 if (FAILED(hres
)) {
10918 ITypeInfo_Release(inh
);
10919 ITypeInfo_Release(tinfo
);
10922 This
->cbSizeVft
= attr
->cbSizeVft
;
10923 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10927 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10928 if(SUCCEEDED(hres
)){
10930 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10931 if(SUCCEEDED(hres
)){
10932 ITypeInfo_Release(inh
);
10936 }while(SUCCEEDED(hres
));
10939 ITypeInfo_Release(inh
);
10940 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10941 This
->cbSizeVft
= 0;
10944 ITypeInfo_Release(tinfo
);
10947 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10948 This
->cbSizeVft
= 0;
10951 ITypeInfo_Release(tinfo
);
10954 } else if (This
->typekind
== TKIND_DISPATCH
)
10955 This
->cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10957 This
->cbSizeVft
= 0;
10959 func_desc
= This
->funcdescs
;
10961 while (i
< This
->cFuncs
) {
10962 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10963 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
10965 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10966 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10968 This
->cbSizeVft
+= This
->pTypeLib
->ptr_size
;
10970 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10973 BOOL reset
= FALSE
;
10975 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10977 iter
= This
->funcdescs
;
10978 while (j
< This
->cFuncs
) {
10979 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10981 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
10984 ++func_desc
->funcdesc
.memid
;
10985 iter
= This
->funcdescs
;
10998 if (user_vft
> This
->cbSizeVft
)
10999 This
->cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11001 for(i
= 0; i
< This
->cVars
; ++i
){
11002 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11003 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11005 BOOL reset
= FALSE
;
11008 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11010 iter
= This
->vardescs
;
11011 while (j
< This
->cVars
) {
11012 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11014 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->cVars
;
11017 ++var_desc
->vardesc
.memid
;
11018 iter
= This
->vardescs
;
11028 ITypeInfo_Release(tinfo
);
11032 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11035 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11036 FIXME("%p %u - stub\n", This
, index
);
11040 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11041 MEMBERID memid
, INVOKEKIND invKind
)
11043 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11044 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11048 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11051 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11052 FIXME("%p %u - stub\n", This
, index
);
11056 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11059 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11060 FIXME("%p %x - stub\n", This
, memid
);
11064 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11067 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11068 FIXME("%p %u - stub\n", This
, index
);
11072 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11073 REFGUID guid
, VARIANT
*varVal
)
11077 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11079 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11081 if (!guid
|| !varVal
)
11082 return E_INVALIDARG
;
11084 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11086 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11089 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11090 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11092 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11093 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11097 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11098 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11100 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11101 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11105 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11106 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11108 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11109 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11113 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11114 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11116 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11117 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11121 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11122 ULONG helpStringContext
)
11124 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11126 TRACE("%p %u\n", This
, helpStringContext
);
11128 This
->dwHelpStringContext
= helpStringContext
;
11133 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11134 UINT index
, ULONG helpStringContext
)
11136 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11137 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11141 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11142 UINT index
, ULONG helpStringContext
)
11144 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11145 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11149 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11151 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11152 FIXME("%p - stub\n", This
);
11156 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11159 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11161 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11164 return E_INVALIDARG
;
11166 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11171 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11172 ICreateTypeInfo2_fnQueryInterface
,
11173 ICreateTypeInfo2_fnAddRef
,
11174 ICreateTypeInfo2_fnRelease
,
11175 ICreateTypeInfo2_fnSetGuid
,
11176 ICreateTypeInfo2_fnSetTypeFlags
,
11177 ICreateTypeInfo2_fnSetDocString
,
11178 ICreateTypeInfo2_fnSetHelpContext
,
11179 ICreateTypeInfo2_fnSetVersion
,
11180 ICreateTypeInfo2_fnAddRefTypeInfo
,
11181 ICreateTypeInfo2_fnAddFuncDesc
,
11182 ICreateTypeInfo2_fnAddImplType
,
11183 ICreateTypeInfo2_fnSetImplTypeFlags
,
11184 ICreateTypeInfo2_fnSetAlignment
,
11185 ICreateTypeInfo2_fnSetSchema
,
11186 ICreateTypeInfo2_fnAddVarDesc
,
11187 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11188 ICreateTypeInfo2_fnSetVarName
,
11189 ICreateTypeInfo2_fnSetTypeDescAlias
,
11190 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11191 ICreateTypeInfo2_fnSetFuncDocString
,
11192 ICreateTypeInfo2_fnSetVarDocString
,
11193 ICreateTypeInfo2_fnSetFuncHelpContext
,
11194 ICreateTypeInfo2_fnSetVarHelpContext
,
11195 ICreateTypeInfo2_fnSetMops
,
11196 ICreateTypeInfo2_fnSetTypeIdldesc
,
11197 ICreateTypeInfo2_fnLayOut
,
11198 ICreateTypeInfo2_fnDeleteFuncDesc
,
11199 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11200 ICreateTypeInfo2_fnDeleteVarDesc
,
11201 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11202 ICreateTypeInfo2_fnDeleteImplType
,
11203 ICreateTypeInfo2_fnSetCustData
,
11204 ICreateTypeInfo2_fnSetFuncCustData
,
11205 ICreateTypeInfo2_fnSetParamCustData
,
11206 ICreateTypeInfo2_fnSetVarCustData
,
11207 ICreateTypeInfo2_fnSetImplTypeCustData
,
11208 ICreateTypeInfo2_fnSetHelpStringContext
,
11209 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11210 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11211 ICreateTypeInfo2_fnInvalidate
,
11212 ICreateTypeInfo2_fnSetName
11215 /******************************************************************************
11216 * ClearCustData (OLEAUT32.171)
11218 * Clear a custom data type's data.
11221 * lpCust [I] The custom data type instance
11226 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11228 if (lpCust
&& lpCust
->cCustData
)
11230 if (lpCust
->prgCustData
)
11234 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11235 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11237 CoTaskMemFree(lpCust
->prgCustData
);
11238 lpCust
->prgCustData
= NULL
;
11240 lpCust
->cCustData
= 0;