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
);
547 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
548 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
552 ITypeLib_Release(*ppTLib
);
554 res
= TYPE_E_LIBNOTREGISTERED
;
560 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
566 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
567 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
568 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
569 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
570 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
571 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
573 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
578 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
579 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
580 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
582 get_interface_key( &tattr
->guid
, keyName
);
583 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
584 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
587 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
588 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
590 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
591 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
592 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
593 (const BYTE
*)PSOA
, sizeof PSOA
);
597 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
598 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
599 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
600 (const BYTE
*)PSOA
, sizeof PSOA
);
604 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
605 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
608 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
609 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
611 StringFromGUID2(&libattr
->guid
, buffer
, 40);
612 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
613 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
614 sprintfW(buffer
, fmtver
, libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
615 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
616 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
624 /******************************************************************************
625 * RegisterTypeLib [OLEAUT32.163]
626 * Adds information about a type library to the System Registry
628 * Docs: ITypeLib FAR * ptlib
629 * Docs: OLECHAR FAR* szFullPath
630 * Docs: OLECHAR FAR* szHelpDir
636 HRESULT WINAPI
RegisterTypeLib(
637 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
638 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
639 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
651 if (ptlib
== NULL
|| szFullPath
== NULL
)
654 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
658 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
661 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
664 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
665 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
669 /* Set the human-readable name of the typelib */
670 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
674 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
675 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
681 /* Make up the name of the typelib path subkey */
682 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
684 /* Create the typelib path subkey */
685 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
686 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
688 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
689 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
697 /* Create the flags subkey */
698 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
699 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
701 /* FIXME: is %u correct? */
702 static const WCHAR formatW
[] = {'%','u',0};
704 sprintfW(buf
, formatW
, attr
->wLibFlags
);
705 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
706 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
714 /* create the helpdir subkey */
715 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
716 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
718 BOOL freeHelpDir
= FALSE
;
721 /* if we created a new key, and helpDir was null, set the helpdir
722 to the directory which contains the typelib. However,
723 if we just opened an existing key, we leave the helpdir alone */
724 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
725 szHelpDir
= SysAllocString(szFullPath
);
726 pIndexStr
= strrchrW(szHelpDir
, '\\');
733 /* if we have an szHelpDir, set it! */
734 if (szHelpDir
!= NULL
) {
735 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
736 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
742 if (freeHelpDir
) SysFreeString(szHelpDir
);
754 /* register OLE Automation-compatible interfaces for this typelib */
755 types
= ITypeLib_GetTypeInfoCount(ptlib
);
756 for (tidx
=0; tidx
<types
; tidx
++) {
757 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
758 LPOLESTR name
= NULL
;
759 ITypeInfo
*tinfo
= NULL
;
761 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
764 case TKIND_INTERFACE
:
765 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
766 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
770 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
771 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
775 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
780 TYPEATTR
*tattr
= NULL
;
781 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
784 TRACE_(typelib
)("guid=%s, flags=%04x (",
785 debugstr_guid(&tattr
->guid
),
788 if (TRACE_ON(typelib
)) {
789 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
809 /* Register all dispinterfaces (which includes dual interfaces) and
810 oleautomation interfaces */
811 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
812 kind
== TKIND_DISPATCH
)
815 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
817 /* register interface<->typelib coupling */
818 TLB_register_interface(attr
, name
, tattr
, 0);
820 /* register TLBs into the opposite registry view, too */
821 if(opposite
== KEY_WOW64_32KEY
||
822 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
823 TLB_register_interface(attr
, name
, tattr
, opposite
);
826 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
829 ITypeInfo_Release(tinfo
);
836 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
841 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
843 WCHAR subKeyName
[50];
846 /* the path to the type */
847 get_interface_key( guid
, subKeyName
);
849 /* Delete its bits */
850 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
853 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
854 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
855 RegDeleteKeyW(subKey
, TypeLibW
);
857 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
860 /******************************************************************************
861 * UnRegisterTypeLib [OLEAUT32.186]
862 * Removes information about a type library from the System Registry
869 HRESULT WINAPI
UnRegisterTypeLib(
870 REFGUID libid
, /* [in] Guid of the library */
871 WORD wVerMajor
, /* [in] major version */
872 WORD wVerMinor
, /* [in] minor version */
873 LCID lcid
, /* [in] locale id */
876 BSTR tlibPath
= NULL
;
879 WCHAR subKeyName
[50];
882 BOOL deleteOtherStuff
;
884 TYPEATTR
* typeAttr
= NULL
;
886 ITypeInfo
* typeInfo
= NULL
;
887 ITypeLib
* typeLib
= NULL
;
890 TRACE("(IID: %s)\n",debugstr_guid(libid
));
892 /* Create the path to the key */
893 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
895 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
897 TRACE("Unsupported syskind %i\n", syskind
);
898 result
= E_INVALIDARG
;
902 /* get the path to the typelib on disk */
903 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
904 result
= E_INVALIDARG
;
908 /* Try and open the key to the type library. */
909 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
910 result
= E_INVALIDARG
;
914 /* Try and load the type library */
915 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
916 result
= TYPE_E_INVALIDSTATE
;
920 /* remove any types registered with this typelib */
921 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
922 for (i
=0; i
<numTypes
; i
++) {
923 /* get the kind of type */
924 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
928 /* skip non-interfaces, and get type info for the type */
929 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
932 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
935 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
939 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
940 kind
== TKIND_DISPATCH
)
943 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
945 TLB_unregister_interface(&typeAttr
->guid
, 0);
947 /* unregister TLBs into the opposite registry view, too */
948 if(opposite
== KEY_WOW64_32KEY
||
949 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
950 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
955 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
957 if (typeInfo
) ITypeInfo_Release(typeInfo
);
961 /* Now, delete the type library path subkey */
962 get_lcid_subkey( lcid
, syskind
, subKeyName
);
963 RegDeleteKeyW(key
, subKeyName
);
964 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
965 RegDeleteKeyW(key
, subKeyName
);
967 /* check if there is anything besides the FLAGS/HELPDIR keys.
968 If there is, we don't delete them */
969 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
970 deleteOtherStuff
= TRUE
;
972 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
973 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
975 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
976 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
977 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
978 deleteOtherStuff
= FALSE
;
982 /* only delete the other parts of the key if we're absolutely sure */
983 if (deleteOtherStuff
) {
984 RegDeleteKeyW(key
, FLAGSW
);
985 RegDeleteKeyW(key
, HELPDIRW
);
989 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
990 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
991 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
995 SysFreeString(tlibPath
);
996 if (typeLib
) ITypeLib_Release(typeLib
);
997 if (key
) RegCloseKey(key
);
1001 /******************************************************************************
1002 * RegisterTypeLibForUser [OLEAUT32.442]
1003 * Adds information about a type library to the user registry
1005 * Docs: ITypeLib FAR * ptlib
1006 * Docs: OLECHAR FAR* szFullPath
1007 * Docs: OLECHAR FAR* szHelpDir
1013 HRESULT WINAPI
RegisterTypeLibForUser(
1014 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
1015 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
1016 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1019 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1020 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1021 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1024 /******************************************************************************
1025 * UnRegisterTypeLibForUser [OLEAUT32.443]
1026 * Removes information about a type library from the user registry
1032 HRESULT WINAPI
UnRegisterTypeLibForUser(
1033 REFGUID libid
, /* [in] GUID of the library */
1034 WORD wVerMajor
, /* [in] major version */
1035 WORD wVerMinor
, /* [in] minor version */
1036 LCID lcid
, /* [in] locale id */
1039 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1040 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1041 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1044 /*======================= ITypeLib implementation =======================*/
1046 typedef struct tagTLBGuid
{
1053 typedef struct tagTLBCustData
1060 /* data structure for import typelibs */
1061 typedef struct tagTLBImpLib
1063 int offset
; /* offset in the file (MSFT)
1064 offset in nametable (SLTG)
1065 just used to identify library while reading
1067 TLBGuid
*guid
; /* libid */
1068 BSTR name
; /* name */
1070 LCID lcid
; /* lcid of imported typelib */
1072 WORD wVersionMajor
; /* major version number */
1073 WORD wVersionMinor
; /* minor version number */
1075 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1076 NULL if not yet loaded */
1080 typedef struct tagTLBString
{
1086 /* internal ITypeLib data */
1087 typedef struct tagITypeLibImpl
1089 ITypeLib2 ITypeLib2_iface
;
1090 ITypeComp ITypeComp_iface
;
1091 ICreateTypeLib2 ICreateTypeLib2_iface
;
1102 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1103 * exported to the application as a UNICODE string.
1105 struct list string_list
;
1106 struct list name_list
;
1107 struct list guid_list
;
1109 const TLBString
*Name
;
1110 const TLBString
*DocString
;
1111 const TLBString
*HelpFile
;
1112 const TLBString
*HelpStringDll
;
1113 DWORD dwHelpContext
;
1114 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1115 struct tagITypeInfoImpl
**typeinfos
;
1116 struct list custdata_list
;
1117 struct list implib_list
;
1118 int ctTypeDesc
; /* number of items in type desc array */
1119 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1120 library. Only used while reading MSFT
1122 struct list ref_list
; /* list of ref types in this typelib */
1123 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1126 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1132 static const ITypeLib2Vtbl tlbvt
;
1133 static const ITypeCompVtbl tlbtcvt
;
1134 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1136 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1138 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1141 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1143 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1146 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1148 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1151 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1153 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1156 /* ITypeLib methods */
1157 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1158 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1160 /*======================= ITypeInfo implementation =======================*/
1162 /* data for referenced types */
1163 typedef struct tagTLBRefType
1165 INT index
; /* Type index for internal ref or for external ref
1166 it the format is SLTG. -2 indicates to
1170 TLBGuid
*guid
; /* guid of the referenced type */
1171 /* if index == TLB_REF_USE_GUID */
1173 HREFTYPE reference
; /* The href of this ref */
1174 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1175 TLB_REF_INTERNAL for internal refs
1176 TLB_REF_NOT_FOUND for broken refs */
1181 #define TLB_REF_USE_GUID -2
1183 #define TLB_REF_INTERNAL (void*)-2
1184 #define TLB_REF_NOT_FOUND (void*)-1
1186 /* internal Parameter data */
1187 typedef struct tagTLBParDesc
1189 const TLBString
*Name
;
1190 struct list custdata_list
;
1193 /* internal Function data */
1194 typedef struct tagTLBFuncDesc
1196 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1197 const TLBString
*Name
; /* the name of this function */
1198 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1200 int HelpStringContext
;
1201 const TLBString
*HelpString
;
1202 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1203 struct list custdata_list
;
1206 /* internal Variable data */
1207 typedef struct tagTLBVarDesc
1209 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1210 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1211 const TLBString
*Name
; /* the name of this variable */
1213 int HelpStringContext
;
1214 const TLBString
*HelpString
;
1215 struct list custdata_list
;
1218 /* internal implemented interface data */
1219 typedef struct tagTLBImplType
1221 HREFTYPE hRef
; /* hRef of interface */
1222 int implflags
; /* IMPLFLAG_*s */
1223 struct list custdata_list
;
1226 /* internal TypeInfo data */
1227 typedef struct tagITypeInfoImpl
1229 ITypeInfo2 ITypeInfo2_iface
;
1230 ITypeComp ITypeComp_iface
;
1231 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1233 BOOL not_attached_to_typelib
;
1238 MEMBERID memidConstructor
;
1239 MEMBERID memidDestructor
;
1240 LPOLESTR lpstrSchema
;
1241 ULONG cbSizeInstance
;
1251 TYPEDESC
*tdescAlias
;
1252 IDLDESC idldescType
;
1254 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1255 int index
; /* index in this typelib; */
1256 HREFTYPE hreftype
; /* hreftype for app object binding */
1257 /* type libs seem to store the doc strings in ascii
1258 * so why should we do it in unicode?
1260 const TLBString
*Name
;
1261 const TLBString
*DocString
;
1262 const TLBString
*DllName
;
1263 const TLBString
*Schema
;
1264 DWORD dwHelpContext
;
1265 DWORD dwHelpStringContext
;
1268 TLBFuncDesc
*funcdescs
;
1271 TLBVarDesc
*vardescs
;
1273 /* Implemented Interfaces */
1274 TLBImplType
*impltypes
;
1276 struct list
*pcustdata_list
;
1277 struct list custdata_list
;
1280 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1282 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1285 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1287 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1290 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1292 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1295 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1297 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1300 static const ITypeInfo2Vtbl tinfvt
;
1301 static const ITypeCompVtbl tcompvt
;
1302 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1304 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1305 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1307 typedef struct tagTLBContext
1309 unsigned int oStart
; /* start of TLB in file */
1310 unsigned int pos
; /* current pos */
1311 unsigned int length
; /* total length */
1312 void *mapping
; /* memory mapping */
1313 MSFT_SegDir
* pTblDir
;
1314 ITypeLibImpl
* pLibInfo
;
1318 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1320 return str
!= NULL
? str
->str
: NULL
;
1323 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1327 return memcmp(left
, str
->str
, len
);
1330 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1332 return guid
!= NULL
? &guid
->guid
: NULL
;
1335 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1337 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1340 static int get_ptr_size(SYSKIND syskind
)
1350 WARN("Unhandled syskind: 0x%x\n", syskind
);
1357 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1358 if (pTD
->vt
& VT_RESERVED
)
1359 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1360 if (pTD
->vt
& VT_BYREF
)
1361 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1362 if (pTD
->vt
& VT_ARRAY
)
1363 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1364 if (pTD
->vt
& VT_VECTOR
)
1365 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1366 switch(pTD
->vt
& VT_TYPEMASK
) {
1367 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1368 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1369 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1370 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1371 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1372 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1373 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1374 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1375 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1376 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1377 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1378 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1379 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1380 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1381 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1382 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1383 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1384 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1385 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1386 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1387 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1388 pTD
->u
.hreftype
); break;
1389 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1390 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1391 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1392 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1394 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1395 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1397 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1398 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1399 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1402 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1406 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1408 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1409 dump_TypeDesc(&edesc
->tdesc
,buf
);
1410 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1411 MESSAGE("\t\tu.paramdesc.wParamFlags");
1412 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1413 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1414 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1415 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1416 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1417 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1418 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1419 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1420 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1422 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1424 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1425 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1426 MESSAGE("Param %d:\n",i
);
1427 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1429 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1430 switch (funcdesc
->funckind
) {
1431 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1432 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1433 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1434 case FUNC_STATIC
: MESSAGE("static");break;
1435 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1436 default: MESSAGE("unknown");break;
1438 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1439 switch (funcdesc
->invkind
) {
1440 case INVOKE_FUNC
: MESSAGE("func");break;
1441 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1442 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1443 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1445 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1446 switch (funcdesc
->callconv
) {
1447 case CC_CDECL
: MESSAGE("cdecl");break;
1448 case CC_PASCAL
: MESSAGE("pascal");break;
1449 case CC_STDCALL
: MESSAGE("stdcall");break;
1450 case CC_SYSCALL
: MESSAGE("syscall");break;
1453 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1454 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1455 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1457 MESSAGE("\telemdescFunc (return value type):\n");
1458 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1461 static const char * const typekind_desc
[] =
1474 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1477 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1478 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1479 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1482 dump_FUNCDESC(&(pfd
->funcdesc
));
1484 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1485 if(pfd
->Entry
== NULL
)
1486 MESSAGE("\tentry: (null)\n");
1487 else if(pfd
->Entry
== (void*)-1)
1488 MESSAGE("\tentry: invalid\n");
1489 else if(IS_INTRESOURCE(pfd
->Entry
))
1490 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1492 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1494 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1498 dump_TLBFuncDescOne(pfd
);
1503 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1507 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1513 static void dump_TLBImpLib(const TLBImpLib
*import
)
1515 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1516 debugstr_w(import
->name
));
1517 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1518 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1521 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1525 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1527 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1528 if(ref
->index
== -1)
1529 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1531 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1533 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1535 TRACE_(typelib
)("in lib\n");
1536 dump_TLBImpLib(ref
->pImpTLInfo
);
1541 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1546 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1547 impl
->hRef
, impl
->implflags
);
1553 static void dump_DispParms(const DISPPARAMS
* pdp
)
1557 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1559 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1561 TRACE("named args:\n");
1562 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1563 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1566 if (pdp
->cArgs
&& pdp
->rgvarg
)
1569 for (index
= 0; index
< pdp
->cArgs
; index
++)
1570 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1574 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1576 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1577 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1578 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1579 TRACE("kind:%s\n", typekind_desc
[pty
->typekind
]);
1580 TRACE("fct:%u var:%u impl:%u\n", pty
->cFuncs
, pty
->cVars
, pty
->cImplTypes
);
1581 TRACE("wTypeFlags: 0x%04x\n", pty
->wTypeFlags
);
1582 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1583 if (pty
->typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1585 dump_TLBFuncDesc(pty
->funcdescs
, pty
->cFuncs
);
1586 dump_TLBVarDesc(pty
->vardescs
, pty
->cVars
);
1587 dump_TLBImplType(pty
->impltypes
, pty
->cImplTypes
);
1590 static void dump_VARDESC(const VARDESC
*v
)
1592 MESSAGE("memid %d\n",v
->memid
);
1593 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1594 MESSAGE("oInst %d\n",v
->u
.oInst
);
1595 dump_ELEMDESC(&(v
->elemdescVar
));
1596 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1597 MESSAGE("varkind %d\n",v
->varkind
);
1600 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1602 /* VT_LPWSTR is largest type that, may appear in type description */
1603 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1604 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1605 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1606 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1607 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1608 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1609 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1610 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1613 static void TLB_abort(void)
1618 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1620 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1621 if (!ret
) ERR("cannot allocate memory\n");
1625 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1627 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1628 if (!ret
) ERR("cannot allocate memory\n");
1632 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1634 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1637 void heap_free(void *ptr
)
1639 HeapFree(GetProcessHeap(), 0, ptr
);
1642 /* returns the size required for a deep copy of a typedesc into a
1644 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1648 if (alloc_initial_space
)
1649 size
+= sizeof(TYPEDESC
);
1655 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1658 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1659 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1665 /* deep copy a typedesc into a flat buffer */
1666 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1671 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1680 dest
->u
.lptdesc
= buffer
;
1681 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1684 dest
->u
.lpadesc
= buffer
;
1685 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1686 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1687 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1693 /* free custom data allocated by MSFT_CustData */
1694 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1696 TLBCustData
*cd
, *cdn
;
1697 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1699 list_remove(&cd
->entry
);
1700 VariantClear(&cd
->data
);
1705 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1710 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1711 ret
= SysAllocStringLen(NULL
, len
- 1);
1712 if (!ret
) return ret
;
1713 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1717 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1718 UINT n
, MEMBERID memid
)
1721 if(funcdescs
->funcdesc
.memid
== memid
)
1729 static inline TLBFuncDesc
*TLB_get_funcdesc_by_name(TLBFuncDesc
*funcdescs
,
1730 UINT n
, const OLECHAR
*name
)
1733 if(!lstrcmpiW(TLB_get_bstr(funcdescs
->Name
), name
))
1741 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1742 UINT n
, MEMBERID memid
)
1745 if(vardescs
->vardesc
.memid
== memid
)
1753 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1754 UINT n
, const OLECHAR
*name
)
1757 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1765 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1767 TLBCustData
*cust_data
;
1768 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1769 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1774 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1775 UINT n
, const OLECHAR
*name
)
1778 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1786 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1788 list_init(&var_desc
->custdata_list
);
1791 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1795 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1800 TLBVarDesc_Constructor(&ret
[n
-1]);
1807 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1811 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1816 list_init(&ret
[n
-1].custdata_list
);
1823 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1825 list_init(&func_desc
->custdata_list
);
1828 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1832 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1837 TLBFuncDesc_Constructor(&ret
[n
-1]);
1844 static void TLBImplType_Constructor(TLBImplType
*impl
)
1846 list_init(&impl
->custdata_list
);
1849 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1853 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1858 TLBImplType_Constructor(&ret
[n
-1]);
1865 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1866 const GUID
*new_guid
, HREFTYPE hreftype
)
1870 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1871 if (IsEqualGUID(&guid
->guid
, new_guid
))
1875 guid
= heap_alloc(sizeof(TLBGuid
));
1879 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1880 guid
->hreftype
= hreftype
;
1882 list_add_tail(guid_list
, &guid
->entry
);
1887 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1889 TLBCustData
*cust_data
;
1901 return DISP_E_BADVARTYPE
;
1904 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1907 cust_data
= heap_alloc(sizeof(TLBCustData
));
1909 return E_OUTOFMEMORY
;
1911 cust_data
->guid
= tlbguid
;
1912 VariantInit(&cust_data
->data
);
1914 list_add_tail(custdata_list
, &cust_data
->entry
);
1916 VariantClear(&cust_data
->data
);
1918 return VariantCopy(&cust_data
->data
, var
);
1921 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1928 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1929 if (strcmpW(str
->str
, new_str
) == 0)
1933 str
= heap_alloc(sizeof(TLBString
));
1937 str
->str
= SysAllocString(new_str
);
1943 list_add_tail(string_list
, &str
->entry
);
1948 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1949 ULONG
*size
, WORD
*align
)
1955 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1959 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1961 ITypeInfo_Release(other
);
1966 *size
= attr
->cbSizeInstance
;
1968 *align
= attr
->cbAlignment
;
1970 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1971 ITypeInfo_Release(other
);
1976 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1977 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1979 ULONG i
, sub
, ptr_size
;
1982 ptr_size
= get_ptr_size(sys
);
2021 *size
= sizeof(DATE
);
2024 *size
= sizeof(VARIANT
);
2026 if(sys
== SYS_WIN32
)
2027 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2031 *size
= sizeof(DECIMAL
);
2038 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2039 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2040 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2045 case VT_USERDEFINED
:
2046 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2048 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2062 /**********************************************************************
2064 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2066 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
2071 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2073 if (where
!= DO_NOT_SEEK
)
2075 where
+= pcx
->oStart
;
2076 if (where
> pcx
->length
)
2079 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2087 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2089 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2090 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2092 MSFT_Seek(pcx
, where
);
2093 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2094 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2099 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2104 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2105 FromLEDWords(buffer
, ret
);
2110 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2115 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2116 FromLEWords(buffer
, ret
);
2121 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2124 MSFT_GuidEntry entry
;
2127 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2129 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2132 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2134 guid
= heap_alloc(sizeof(TLBGuid
));
2136 guid
->offset
= offs
;
2137 guid
->guid
= entry
.guid
;
2138 guid
->hreftype
= entry
.hreftype
;
2140 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2142 offs
+= sizeof(MSFT_GuidEntry
);
2146 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2150 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2151 if(ret
->offset
== offset
){
2152 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2160 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2162 MSFT_NameIntro niName
;
2166 ERR_(typelib
)("bad offset %d\n", offset
);
2170 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2171 pcx
->pTblDir
->pNametab
.offset
+offset
);
2173 return niName
.hreftype
;
2176 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2179 MSFT_NameIntro intro
;
2181 int offs
= 0, lengthInChars
;
2183 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2187 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2190 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2191 intro
.namelen
&= 0xFF;
2192 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2194 len_piece
= (len_piece
+ 4) & ~0x3;
2198 string
= heap_alloc(len_piece
+ 1);
2199 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2200 string
[intro
.namelen
] = '\0';
2202 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2203 string
, -1, NULL
, 0);
2204 if (!lengthInChars
) {
2206 return E_UNEXPECTED
;
2209 tlbstr
= heap_alloc(sizeof(TLBString
));
2211 tlbstr
->offset
= offs
;
2212 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2213 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2217 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2223 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2227 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2228 if (tlbstr
->offset
== offset
) {
2229 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2237 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2241 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2242 if (tlbstr
->offset
== offset
) {
2243 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2252 * read a value and fill a VARIANT structure
2254 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2258 TRACE_(typelib
)("\n");
2260 if(offset
<0) { /* data are packed in here */
2261 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2262 V_I4(pVar
) = offset
& 0x3ffffff;
2265 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2266 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2267 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2268 switch (V_VT(pVar
)){
2269 case VT_EMPTY
: /* FIXME: is this right? */
2270 case VT_NULL
: /* FIXME: is this right? */
2271 case VT_I2
: /* this should not happen */
2282 case VT_VOID
: /* FIXME: is this right? */
2290 case VT_DECIMAL
: /* FIXME: is this right? */
2293 /* pointer types with known behaviour */
2296 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2298 V_BSTR(pVar
) = NULL
;
2300 ptr
= heap_alloc_zero(size
);
2301 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2302 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2303 /* FIXME: do we need a AtoW conversion here? */
2304 V_UNION(pVar
, bstrVal
[size
])='\0';
2305 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2310 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2317 case VT_USERDEFINED
:
2323 case VT_STREAMED_OBJECT
:
2324 case VT_STORED_OBJECT
:
2325 case VT_BLOB_OBJECT
:
2330 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2334 if(size
>0) /* (big|small) endian correct? */
2335 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2339 * create a linked list with custom data
2341 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2347 TRACE_(typelib
)("\n");
2349 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2353 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2354 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2355 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2356 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2357 list_add_head(custdata_list
, &pNew
->entry
);
2358 offset
= entry
.next
;
2363 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2366 pTd
->vt
=type
& VT_TYPEMASK
;
2368 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2370 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2373 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2375 return (invkind
== INVOKE_PROPERTYGET
||
2376 invkind
== INVOKE_PROPERTYPUT
||
2377 invkind
== INVOKE_PROPERTYPUTREF
);
2381 MSFT_DoFuncs(TLBContext
* pcx
,
2386 TLBFuncDesc
** pptfd
)
2389 * member information is stored in a data structure at offset
2390 * indicated by the memoffset field of the typeinfo structure
2391 * There are several distinctive parts.
2392 * The first part starts with a field that holds the total length
2393 * of this (first) part excluding this field. Then follow the records,
2394 * for each member there is one record.
2396 * The first entry is always the length of the record (including this
2398 * The rest of the record depends on the type of the member. If there is
2399 * a field indicating the member type (function, variable, interface, etc)
2400 * I have not found it yet. At this time we depend on the information
2401 * in the type info and the usual order how things are stored.
2403 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2406 * Third is an equal sized array with file offsets to the name entry
2409 * The fourth and last (?) part is an array with offsets to the records
2410 * in the first part of this file segment.
2413 int infolen
, nameoffset
, reclength
, i
;
2414 int recoffset
= offset
+ sizeof(INT
);
2416 char *recbuf
= heap_alloc(0xffff);
2417 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2418 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2420 TRACE_(typelib
)("\n");
2422 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2424 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2426 for ( i
= 0; i
< cFuncs
; i
++ )
2430 /* name, eventually add to a hash table */
2431 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2432 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2434 /* read the function information record */
2435 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2437 reclength
&= 0xffff;
2439 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2441 /* size without argument data */
2442 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2443 if (pFuncRec
->FKCCIC
& 0x1000)
2444 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2446 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2447 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2449 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2450 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2452 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2454 if (pFuncRec
->FKCCIC
& 0x2000 )
2456 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2457 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2458 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2461 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2464 ptfd
->Entry
= (TLBString
*)-1;
2466 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2467 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2469 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2470 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2472 /* fill the FuncDesc Structure */
2473 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2474 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2476 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2477 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2478 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2479 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2480 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2481 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2482 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2484 /* nameoffset is sometimes -1 on the second half of a propget/propput
2485 * pair of functions */
2486 if ((nameoffset
== -1) && (i
> 0) &&
2487 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2488 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2489 ptfd
->Name
= ptfd_prev
->Name
;
2491 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2495 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2497 /* do the parameters/arguments */
2498 if(pFuncRec
->nrargs
)
2501 MSFT_ParameterInfo paraminfo
;
2503 ptfd
->funcdesc
.lprgelemdescParam
=
2504 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2506 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2508 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2509 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2511 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2513 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2519 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2522 if (paraminfo
.oName
!= -1)
2523 ptfd
->pParamDesc
[j
].Name
=
2524 MSFT_ReadName( pcx
, paraminfo
.oName
);
2525 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2528 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2529 (pFuncRec
->FKCCIC
& 0x1000) )
2531 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2533 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2535 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2537 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2538 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2540 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2544 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2547 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2548 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2549 pFuncRec
->FKCCIC
& 0x80 )
2552 pFuncRec
->oArgCustData
[j
],
2553 &ptfd
->pParamDesc
[j
].custdata_list
);
2556 /* SEEK value = jump to offset,
2557 * from there jump to the end of record,
2558 * go back by (j-1) arguments
2560 MSFT_ReadLEDWords( ¶minfo
,
2561 sizeof(MSFT_ParameterInfo
), pcx
,
2562 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2563 * sizeof(MSFT_ParameterInfo
)));
2567 /* scode is not used: archaic win16 stuff FIXME: right? */
2568 ptfd
->funcdesc
.cScodes
= 0 ;
2569 ptfd
->funcdesc
.lprgscode
= NULL
;
2573 recoffset
+= reclength
;
2578 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2579 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2581 int infolen
, nameoffset
, reclength
;
2583 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2588 TRACE_(typelib
)("\n");
2590 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2591 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2592 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2593 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2594 recoffset
+= offset
+sizeof(INT
);
2595 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2596 /* name, eventually add to a hash table */
2597 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2598 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2599 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2600 /* read the variable information record */
2601 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2603 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2606 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2607 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2609 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2610 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2612 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2613 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2615 /* fill the VarDesc Structure */
2616 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2617 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2618 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2619 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2620 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2621 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2622 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2623 if(pVarRec
->VarKind
== VAR_CONST
){
2624 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2625 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2626 pVarRec
->OffsValue
, pcx
);
2628 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2629 recoffset
+= reclength
;
2633 /* process Implemented Interfaces of a com class */
2634 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2638 MSFT_RefRecord refrec
;
2641 TRACE_(typelib
)("\n");
2643 pTI
->impltypes
= TLBImplType_Alloc(count
);
2644 pImpl
= pTI
->impltypes
;
2645 for(i
=0;i
<count
;i
++){
2646 if(offset
<0) break; /* paranoia */
2647 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2648 pImpl
->hRef
= refrec
.reftype
;
2649 pImpl
->implflags
=refrec
.flags
;
2650 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2651 offset
=refrec
.onext
;
2657 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2658 * and some structures, and fix the alignment */
2659 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2661 if(info
->typekind
== TKIND_ALIAS
){
2662 switch(info
->tdescAlias
->vt
){
2670 info
->cbSizeInstance
= sizeof(void*);
2671 info
->cbAlignment
= sizeof(void*);
2674 case VT_USERDEFINED
:
2675 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->cbSizeInstance
, &info
->cbAlignment
);
2678 info
->cbSizeInstance
= sizeof(VARIANT
);
2679 info
->cbAlignment
= 8;
2681 if(info
->cbSizeInstance
< sizeof(void*))
2682 info
->cbAlignment
= info
->cbSizeInstance
;
2684 info
->cbAlignment
= sizeof(void*);
2687 }else if(info
->typekind
== TKIND_INTERFACE
||
2688 info
->typekind
== TKIND_DISPATCH
||
2689 info
->typekind
== TKIND_COCLASS
){
2690 info
->cbSizeInstance
= sizeof(void*);
2691 info
->cbAlignment
= sizeof(void*);
2697 * process a typeinfo record
2699 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2702 ITypeLibImpl
* pLibInfo
)
2704 MSFT_TypeInfoBase tiBase
;
2705 ITypeInfoImpl
*ptiRet
;
2707 TRACE_(typelib
)("count=%u\n", count
);
2709 ptiRet
= ITypeInfoImpl_Constructor();
2710 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2711 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2713 /* this is where we are coming from */
2714 ptiRet
->pTypeLib
= pLibInfo
;
2715 ptiRet
->index
=count
;
2717 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2718 ptiRet
->lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2719 ptiRet
->lpstrSchema
=NULL
; /* reserved */
2720 ptiRet
->cbSizeInstance
=tiBase
.size
;
2721 ptiRet
->typekind
=tiBase
.typekind
& 0xF;
2722 ptiRet
->cFuncs
=LOWORD(tiBase
.cElement
);
2723 ptiRet
->cVars
=HIWORD(tiBase
.cElement
);
2724 ptiRet
->cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2725 ptiRet
->wTypeFlags
=tiBase
.flags
;
2726 ptiRet
->wMajorVerNum
=LOWORD(tiBase
.version
);
2727 ptiRet
->wMinorVerNum
=HIWORD(tiBase
.version
);
2728 ptiRet
->cImplTypes
=tiBase
.cImplTypes
;
2729 ptiRet
->cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2730 if(ptiRet
->typekind
== TKIND_ALIAS
){
2732 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2733 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2734 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2738 /* IDLDESC idldescType; *//* never saw this one != zero */
2740 /* name, eventually add to a hash table */
2741 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2742 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2743 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2745 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2746 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2747 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2749 if (ptiRet
->typekind
== TKIND_MODULE
)
2750 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2752 /* note: InfoType's Help file and HelpStringDll come from the containing
2753 * library. Further HelpString and Docstring appear to be the same thing :(
2756 if(ptiRet
->cFuncs
>0 )
2757 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->cFuncs
,
2759 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2761 if(ptiRet
->cVars
>0 )
2762 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->cFuncs
,
2764 tiBase
.memoffset
, &ptiRet
->vardescs
);
2765 if(ptiRet
->cImplTypes
>0 ) {
2766 switch(ptiRet
->typekind
)
2769 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->cImplTypes
,
2772 case TKIND_DISPATCH
:
2773 /* This is not -1 when the interface is a non-base dual interface or
2774 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2775 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2779 if (tiBase
.datatype1
!= -1)
2781 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2782 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2786 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2787 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2791 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2793 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2794 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2795 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2796 typekind_desc
[ptiRet
->typekind
]);
2797 if (TRACE_ON(typelib
))
2798 dump_TypeInfo(ptiRet
);
2803 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2806 INT16 len_str
, len_piece
;
2807 int offs
= 0, lengthInChars
;
2809 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2813 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2816 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2817 len_piece
= len_str
+ sizeof(INT16
);
2819 len_piece
= (len_piece
+ 4) & ~0x3;
2823 string
= heap_alloc(len_piece
+ 1);
2824 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2825 string
[len_str
] = '\0';
2827 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2828 string
, -1, NULL
, 0);
2829 if (!lengthInChars
) {
2831 return E_UNEXPECTED
;
2834 tlbstr
= heap_alloc(sizeof(TLBString
));
2836 tlbstr
->offset
= offs
;
2837 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2838 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2842 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2848 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2853 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2854 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2855 MSFT_ImpInfo impinfo
;
2858 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2860 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2861 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2863 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2864 if(pImpLib
->offset
==impinfo
.oImpFile
)
2867 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2868 ref
->reference
= offs
;
2869 ref
->pImpTLInfo
= pImpLib
;
2870 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2871 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2872 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2873 ref
->index
= TLB_REF_USE_GUID
;
2875 ref
->index
= impinfo
.oGuid
;
2877 ERR("Cannot find a reference\n");
2878 ref
->reference
= -1;
2879 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2882 offs
+= sizeof(impinfo
);
2888 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2889 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2890 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2893 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2894 static CRITICAL_SECTION cache_section
;
2895 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2897 0, 0, &cache_section
,
2898 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2899 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2901 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2904 typedef struct TLB_PEFile
2906 IUnknown IUnknown_iface
;
2909 HRSRC typelib_resource
;
2910 HGLOBAL typelib_global
;
2911 LPVOID typelib_base
;
2914 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2916 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2919 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2921 if (IsEqualIID(riid
, &IID_IUnknown
))
2924 IUnknown_AddRef(iface
);
2928 return E_NOINTERFACE
;
2931 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2933 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2934 return InterlockedIncrement(&This
->refs
);
2937 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2939 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2940 ULONG refs
= InterlockedDecrement(&This
->refs
);
2943 if (This
->typelib_global
)
2944 FreeResource(This
->typelib_global
);
2946 FreeLibrary(This
->dll
);
2952 static const IUnknownVtbl TLB_PEFile_Vtable
=
2954 TLB_PEFile_QueryInterface
,
2959 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2962 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2964 This
= heap_alloc(sizeof(TLB_PEFile
));
2966 return E_OUTOFMEMORY
;
2968 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2971 This
->typelib_resource
= NULL
;
2972 This
->typelib_global
= NULL
;
2973 This
->typelib_base
= NULL
;
2975 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2976 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2980 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2981 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2982 if (This
->typelib_resource
)
2984 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2985 if (This
->typelib_global
)
2987 This
->typelib_base
= LockResource(This
->typelib_global
);
2989 if (This
->typelib_base
)
2991 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2992 *ppBase
= This
->typelib_base
;
2993 *ppFile
= &This
->IUnknown_iface
;
2999 TRACE("No TYPELIB resource found\n");
3003 TLB_PEFile_Release(&This
->IUnknown_iface
);
3007 typedef struct TLB_NEFile
3009 IUnknown IUnknown_iface
;
3011 LPVOID typelib_base
;
3014 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
3016 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
3019 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3021 if (IsEqualIID(riid
, &IID_IUnknown
))
3024 IUnknown_AddRef(iface
);
3028 return E_NOINTERFACE
;
3031 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
3033 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3034 return InterlockedIncrement(&This
->refs
);
3037 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
3039 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3040 ULONG refs
= InterlockedDecrement(&This
->refs
);
3043 heap_free(This
->typelib_base
);
3049 static const IUnknownVtbl TLB_NEFile_Vtable
=
3051 TLB_NEFile_QueryInterface
,
3056 /***********************************************************************
3057 * read_xx_header [internal]
3059 static int read_xx_header( HFILE lzfd
)
3061 IMAGE_DOS_HEADER mzh
;
3064 LZSeek( lzfd
, 0, SEEK_SET
);
3065 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3067 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3070 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3071 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3074 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3076 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3077 return IMAGE_OS2_SIGNATURE
;
3078 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3079 return IMAGE_NT_SIGNATURE
;
3082 WARN("Can't handle %s files.\n", magic
);
3087 /***********************************************************************
3088 * find_ne_resource [internal]
3090 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3091 DWORD
*resLen
, DWORD
*resOff
)
3093 IMAGE_OS2_HEADER nehd
;
3094 NE_TYPEINFO
*typeInfo
;
3095 NE_NAMEINFO
*nameInfo
;
3101 /* Read in NE header */
3102 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3103 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3105 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3108 TRACE("No resources in NE dll\n" );
3112 /* Read in resource table */
3113 resTab
= heap_alloc( resTabSize
);
3114 if ( !resTab
) return FALSE
;
3116 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3117 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3119 heap_free( resTab
);
3124 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3126 if (!IS_INTRESOURCE(typeid)) /* named type */
3128 BYTE len
= strlen( typeid );
3129 while (typeInfo
->type_id
)
3131 if (!(typeInfo
->type_id
& 0x8000))
3133 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3134 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
3136 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3137 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3140 else /* numeric type id */
3142 WORD id
= LOWORD(typeid) | 0x8000;
3143 while (typeInfo
->type_id
)
3145 if (typeInfo
->type_id
== id
) goto found_type
;
3146 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3147 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3150 TRACE("No typeid entry found for %p\n", typeid );
3151 heap_free( resTab
);
3155 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3157 if (!IS_INTRESOURCE(resid
)) /* named resource */
3159 BYTE len
= strlen( resid
);
3160 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3162 BYTE
*p
= resTab
+ nameInfo
->id
;
3163 if (nameInfo
->id
& 0x8000) continue;
3164 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3167 else /* numeric resource id */
3169 WORD id
= LOWORD(resid
) | 0x8000;
3170 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3171 if (nameInfo
->id
== id
) goto found_name
;
3173 TRACE("No resid entry found for %p\n", typeid );
3174 heap_free( resTab
);
3178 /* Return resource data */
3179 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3180 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3182 heap_free( resTab
);
3186 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3190 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3193 This
= heap_alloc(sizeof(TLB_NEFile
));
3194 if (!This
) return E_OUTOFMEMORY
;
3196 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3198 This
->typelib_base
= NULL
;
3200 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3201 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3203 DWORD reslen
, offset
;
3204 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3206 This
->typelib_base
= heap_alloc(reslen
);
3207 if( !This
->typelib_base
)
3211 LZSeek( lzfd
, offset
, SEEK_SET
);
3212 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3214 *ppBase
= This
->typelib_base
;
3215 *pdwTLBLength
= reslen
;
3216 *ppFile
= &This
->IUnknown_iface
;
3222 if( lzfd
>= 0) LZClose( lzfd
);
3223 TLB_NEFile_Release(&This
->IUnknown_iface
);
3227 typedef struct TLB_Mapping
3229 IUnknown IUnknown_iface
;
3233 LPVOID typelib_base
;
3236 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3238 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3241 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3243 if (IsEqualIID(riid
, &IID_IUnknown
))
3246 IUnknown_AddRef(iface
);
3250 return E_NOINTERFACE
;
3253 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3255 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3256 return InterlockedIncrement(&This
->refs
);
3259 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3261 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3262 ULONG refs
= InterlockedDecrement(&This
->refs
);
3265 if (This
->typelib_base
)
3266 UnmapViewOfFile(This
->typelib_base
);
3268 CloseHandle(This
->mapping
);
3269 if (This
->file
!= INVALID_HANDLE_VALUE
)
3270 CloseHandle(This
->file
);
3276 static const IUnknownVtbl TLB_Mapping_Vtable
=
3278 TLB_Mapping_QueryInterface
,
3283 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3287 This
= heap_alloc(sizeof(TLB_Mapping
));
3289 return E_OUTOFMEMORY
;
3291 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3293 This
->file
= INVALID_HANDLE_VALUE
;
3294 This
->mapping
= NULL
;
3295 This
->typelib_base
= NULL
;
3297 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3298 if (INVALID_HANDLE_VALUE
!= This
->file
)
3300 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3303 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3304 if(This
->typelib_base
)
3306 /* retrieve file size */
3307 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3308 *ppBase
= This
->typelib_base
;
3309 *ppFile
= &This
->IUnknown_iface
;
3315 IUnknown_Release(&This
->IUnknown_iface
);
3316 return TYPE_E_CANTLOADLIBRARY
;
3319 /****************************************************************************
3322 * find the type of the typelib file and map the typelib resource into
3326 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3327 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3329 ITypeLibImpl
*entry
;
3332 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3333 LPVOID pBase
= NULL
;
3334 DWORD dwTLBLength
= 0;
3335 IUnknown
*pFile
= NULL
;
3340 index_str
= strrchrW(pszFileName
, '\\');
3341 if(index_str
&& *++index_str
!= '\0')
3344 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3345 if(*end_ptr
== '\0')
3347 int str_len
= index_str
- pszFileName
- 1;
3349 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3350 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3355 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3357 if(strchrW(file
, '\\'))
3359 lstrcpyW(pszPath
, file
);
3363 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3364 pszPath
[len
] = '\\';
3365 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3369 if(file
!= pszFileName
) heap_free(file
);
3371 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3372 if(h
!= INVALID_HANDLE_VALUE
){
3373 FILE_NAME_INFORMATION
*info
;
3374 char data
[MAX_PATH
* sizeof(WCHAR
) + sizeof(info
->FileNameLength
)];
3377 info
= (FILE_NAME_INFORMATION
*)data
;
3378 /* GetFileInformationByHandleEx returns the path of the file without
3379 * WOW64 redirection */
3380 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, data
, sizeof(data
));
3382 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3383 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3388 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3390 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3391 EnterCriticalSection(&cache_section
);
3392 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3394 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3396 TRACE("cache hit\n");
3397 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3398 ITypeLib2_AddRef(*ppTypeLib
);
3399 LeaveCriticalSection(&cache_section
);
3403 LeaveCriticalSection(&cache_section
);
3405 /* now actually load and parse the typelib */
3407 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3408 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3409 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3410 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3411 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3414 if (dwTLBLength
>= 4)
3416 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3417 if (dwSignature
== MSFT_SIGNATURE
)
3418 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3419 else if (dwSignature
== SLTG_SIGNATURE
)
3420 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3423 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3424 ret
= TYPE_E_CANTLOADLIBRARY
;
3428 ret
= TYPE_E_CANTLOADLIBRARY
;
3429 IUnknown_Release(pFile
);
3433 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3435 TRACE("adding to cache\n");
3436 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3437 lstrcpyW(impl
->path
, pszPath
);
3438 /* We should really canonicalise the path here. */
3439 impl
->index
= index
;
3441 /* FIXME: check if it has added already in the meantime */
3442 EnterCriticalSection(&cache_section
);
3443 list_add_head(&tlb_cache
, &impl
->entry
);
3444 LeaveCriticalSection(&cache_section
);
3450 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3452 ret
= TYPE_E_CANTLOADLIBRARY
;
3459 /*================== ITypeLib(2) Methods ===================================*/
3461 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3463 ITypeLibImpl
* pTypeLibImpl
;
3465 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3466 if (!pTypeLibImpl
) return NULL
;
3468 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3469 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3470 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3471 pTypeLibImpl
->ref
= 1;
3473 list_init(&pTypeLibImpl
->implib_list
);
3474 list_init(&pTypeLibImpl
->custdata_list
);
3475 list_init(&pTypeLibImpl
->name_list
);
3476 list_init(&pTypeLibImpl
->string_list
);
3477 list_init(&pTypeLibImpl
->guid_list
);
3478 list_init(&pTypeLibImpl
->ref_list
);
3479 pTypeLibImpl
->dispatch_href
= -1;
3481 return pTypeLibImpl
;
3484 /****************************************************************************
3485 * ITypeLib2_Constructor_MSFT
3487 * loading an MSFT typelib from an in-memory image
3489 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3493 MSFT_Header tlbHeader
;
3494 MSFT_SegDir tlbSegDir
;
3495 ITypeLibImpl
* pTypeLibImpl
;
3498 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3500 pTypeLibImpl
= TypeLibImpl_Constructor();
3501 if (!pTypeLibImpl
) return NULL
;
3503 /* get pointer to beginning of typelib data */
3507 cx
.pLibInfo
= pTypeLibImpl
;
3508 cx
.length
= dwTLBLength
;
3511 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3512 TRACE_(typelib
)("header:\n");
3513 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3514 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3515 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3518 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3520 /* there is a small amount of information here until the next important
3522 * the segment directory . Try to calculate the amount of data */
3523 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3525 /* now read the segment directory */
3526 TRACE("read segment directory (at %d)\n",lPSegDir
);
3527 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3528 cx
.pTblDir
= &tlbSegDir
;
3530 /* just check two entries */
3531 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3533 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3534 heap_free(pTypeLibImpl
);
3538 MSFT_ReadAllNames(&cx
);
3539 MSFT_ReadAllStrings(&cx
);
3540 MSFT_ReadAllGuids(&cx
);
3542 /* now fill our internal data */
3543 /* TLIBATTR fields */
3544 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3546 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3547 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3548 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3549 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3550 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3552 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3553 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3555 /* name, eventually add to a hash table */
3556 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3559 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3560 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3562 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3565 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3566 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3569 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3572 if(tlbHeader
.CustomDataOffset
>= 0)
3574 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3577 /* fill in type descriptions */
3578 if(tlbSegDir
.pTypdescTab
.length
> 0)
3580 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3582 pTypeLibImpl
->ctTypeDesc
= cTD
;
3583 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3584 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3587 /* FIXME: add several sanity checks here */
3588 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3589 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3591 /* FIXME: check safearray */
3593 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3595 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3597 else if(td
[0] == VT_CARRAY
)
3599 /* array descr table here */
3600 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3602 else if(td
[0] == VT_USERDEFINED
)
3604 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3606 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3609 /* second time around to fill the array subscript info */
3612 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3613 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3615 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3616 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3619 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3621 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3623 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3625 for(j
= 0; j
<td
[2]; j
++)
3627 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3628 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3629 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3630 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3635 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3636 ERR("didn't find array description data\n");
3641 /* imported type libs */
3642 if(tlbSegDir
.pImpFiles
.offset
>0)
3645 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3648 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3652 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3653 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3654 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3656 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3657 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3658 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3659 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3662 name
= heap_alloc_zero(size
+1);
3663 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3664 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3667 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3668 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3670 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3674 MSFT_ReadAllRefs(&cx
);
3676 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3679 if(tlbHeader
.nrtypeinfos
>= 0 )
3681 ITypeInfoImpl
**ppTI
;
3683 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3685 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3687 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3690 (pTypeLibImpl
->TypeInfoCount
)++;
3695 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3696 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3697 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3701 TRACE("(%p)\n", pTypeLibImpl
);
3702 return &pTypeLibImpl
->ITypeLib2_iface
;
3706 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3712 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3713 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3717 guid
->Data4
[0] = s
>> 8;
3718 guid
->Data4
[1] = s
& 0xff;
3721 for(i
= 0; i
< 6; i
++) {
3722 memcpy(b
, str
+ 24 + 2 * i
, 2);
3723 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3728 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3735 bytelen
= *(const WORD
*)ptr
;
3736 if(bytelen
== 0xffff) return 2;
3738 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3739 tmp_str
= SysAllocStringLen(NULL
, len
);
3741 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3742 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3743 SysFreeString(tmp_str
);
3748 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3753 bytelen
= *(const WORD
*)ptr
;
3754 if(bytelen
== 0xffff) return 2;
3755 *str
= heap_alloc(bytelen
+ 1);
3756 memcpy(*str
, ptr
+ 2, bytelen
);
3757 (*str
)[bytelen
] = '\0';
3761 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3766 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3767 if (tlbstr
->offset
== offset
)
3771 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3772 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3773 SysFreeString(tmp_str
);
3778 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3780 char *ptr
= pLibBlk
;
3783 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3784 FIXME("libblk magic = %04x\n", w
);
3789 if((w
= *(WORD
*)ptr
) != 0xffff) {
3790 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3795 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3797 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3799 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3802 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3803 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3806 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3807 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3809 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3812 ptr
+= 4; /* skip res12 */
3814 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3817 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3820 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3823 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3824 ptr
+= sizeof(GUID
);
3826 return ptr
- (char*)pLibBlk
;
3829 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3834 } sltg_ref_lookup_t
;
3836 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3837 HREFTYPE
*typelib_ref
)
3839 if(table
&& typeinfo_ref
< table
->num
)
3841 *typelib_ref
= table
->refs
[typeinfo_ref
];
3845 ERR_(typelib
)("Unable to find reference\n");
3850 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3855 if((*pType
& 0xe00) == 0xe00) {
3857 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3858 pTD
= pTD
->u
.lptdesc
;
3860 switch(*pType
& 0x3f) {
3863 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3864 pTD
= pTD
->u
.lptdesc
;
3867 case VT_USERDEFINED
:
3868 pTD
->vt
= VT_USERDEFINED
;
3869 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3875 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3878 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3880 pTD
->vt
= VT_CARRAY
;
3881 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3882 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3883 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3884 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3886 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3892 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3896 pTD
->vt
= VT_SAFEARRAY
;
3897 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3898 pTD
= pTD
->u
.lptdesc
;
3902 pTD
->vt
= *pType
& 0x3f;
3911 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3912 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3914 /* Handle [in/out] first */
3915 if((*pType
& 0xc000) == 0xc000)
3916 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3917 else if(*pType
& 0x8000)
3918 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3919 else if(*pType
& 0x4000)
3920 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3922 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3925 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3928 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3930 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3934 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3939 TLBRefType
*ref_type
;
3940 sltg_ref_lookup_t
*table
;
3941 HREFTYPE typelib_ref
;
3943 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3944 FIXME("Ref magic = %x\n", pRef
->magic
);
3947 name
= ( (char*)pRef
->names
+ pRef
->number
);
3949 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3950 table
->num
= pRef
->number
>> 3;
3952 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3954 /* We don't want the first href to be 0 */
3955 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3957 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3959 unsigned int lib_offs
, type_num
;
3961 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3963 name
+= SLTG_ReadStringA(name
, &refname
);
3964 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3965 FIXME_(typelib
)("Can't sscanf ref\n");
3966 if(lib_offs
!= 0xffff) {
3969 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3970 if(import
->offset
== lib_offs
)
3973 if(&import
->entry
== &pTL
->implib_list
) {
3974 char fname
[MAX_PATH
+1];
3978 import
= heap_alloc_zero(sizeof(*import
));
3979 import
->offset
= lib_offs
;
3980 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3981 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3982 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3983 &import
->wVersionMajor
,
3984 &import
->wVersionMinor
,
3985 &import
->lcid
, fname
) != 4) {
3986 FIXME_(typelib
)("can't sscanf ref %s\n",
3987 pNameTable
+ lib_offs
+ 40);
3989 len
= strlen(fname
);
3990 if(fname
[len
-1] != '#')
3991 FIXME("fname = %s\n", fname
);
3992 fname
[len
-1] = '\0';
3993 import
->name
= TLB_MultiByteToBSTR(fname
);
3994 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3996 ref_type
->pImpTLInfo
= import
;
3998 /* Store a reference to IDispatch */
3999 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
4000 pTL
->dispatch_href
= typelib_ref
;
4002 } else { /* internal ref */
4003 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
4005 ref_type
->reference
= typelib_ref
;
4006 ref_type
->index
= type_num
;
4009 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
4011 table
->refs
[ref
] = typelib_ref
;
4014 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
4015 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
4016 dump_TLBRefType(pTL
);
4020 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
4021 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
4023 SLTG_ImplInfo
*info
;
4024 TLBImplType
*pImplType
;
4025 /* I don't really get this structure, usually it's 0x16 bytes
4026 long, but iuser.tlb contains some that are 0x18 bytes long.
4027 That's ok because we can use the next ptr to jump to the next
4028 one. But how do we know the length of the last one? The WORD
4029 at offs 0x8 might be the clue. For now I'm just assuming that
4030 the last one is the regular 0x16 bytes. */
4032 info
= (SLTG_ImplInfo
*)pBlk
;
4035 if(info
->next
== 0xffff)
4037 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4040 info
= (SLTG_ImplInfo
*)pBlk
;
4041 pTI
->impltypes
= TLBImplType_Alloc(pTI
->cImplTypes
);
4042 pImplType
= pTI
->impltypes
;
4044 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4045 pImplType
->implflags
= info
->impltypeflags
;
4048 if(info
->next
== 0xffff)
4051 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4052 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4054 info
++; /* see comment at top of function */
4058 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4059 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4061 TLBVarDesc
*pVarDesc
;
4062 const TLBString
*prevName
= NULL
;
4063 SLTG_Variable
*pItem
;
4067 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4069 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4070 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4072 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4074 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4075 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4076 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4080 if (pItem
->name
== 0xfffe)
4081 pVarDesc
->Name
= prevName
;
4083 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4085 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4086 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4087 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4089 if(pItem
->flags
& 0x02)
4090 pType
= &pItem
->type
;
4092 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4094 if (pItem
->flags
& ~0xda)
4095 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4097 SLTG_DoElem(pType
, pBlk
,
4098 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4100 if (TRACE_ON(typelib
)) {
4102 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4103 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4106 if (pItem
->flags
& 0x40) {
4107 TRACE_(typelib
)("VAR_DISPATCH\n");
4108 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4110 else if (pItem
->flags
& 0x10) {
4111 TRACE_(typelib
)("VAR_CONST\n");
4112 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4113 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4114 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4115 if (pItem
->flags
& 0x08)
4116 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4118 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4124 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4126 TRACE_(typelib
)("len = %u\n", len
);
4127 if (len
== 0xffff) {
4130 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4131 str
= SysAllocStringLen(NULL
, alloc_len
);
4132 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4134 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4135 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4144 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4145 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4148 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4153 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4154 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4155 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4158 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4159 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4161 if (pItem
->flags
& 0x80)
4162 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4164 prevName
= pVarDesc
->Name
;
4169 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4170 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4172 SLTG_Function
*pFunc
;
4174 TLBFuncDesc
*pFuncDesc
;
4176 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4178 pFuncDesc
= pTI
->funcdescs
;
4179 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4180 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4185 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4186 case SLTG_FUNCTION_MAGIC
:
4187 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4189 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4190 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4192 case SLTG_STATIC_FUNCTION_MAGIC
:
4193 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4196 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4199 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4201 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4202 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4203 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4204 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4205 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4206 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4208 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4209 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4211 if(pFunc
->retnextopt
& 0x80)
4212 pType
= &pFunc
->rettype
;
4214 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4216 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4218 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4219 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4220 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4222 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4224 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4225 char *paramName
= pNameTable
+ *pArg
;
4227 /* If arg type follows then paramName points to the 2nd
4228 letter of the name, else the next WORD is an offset to
4229 the arg type and paramName points to the first letter.
4230 So let's take one char off paramName and see if we're
4231 pointing at an alpha-numeric char. However if *pArg is
4232 0xffff or 0xfffe then the param has no name, the former
4233 meaning that the next WORD is the type, the latter
4234 meaning that the next WORD is an offset to the type. */
4239 else if(*pArg
== 0xfffe) {
4243 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4248 if(HaveOffs
) { /* the next word is an offset to type */
4249 pType
= (WORD
*)(pBlk
+ *pArg
);
4250 SLTG_DoElem(pType
, pBlk
,
4251 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4256 pArg
= SLTG_DoElem(pArg
, pBlk
,
4257 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4260 /* Are we an optional param ? */
4261 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4262 pFuncDesc
->funcdesc
.cParamsOpt
)
4263 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4266 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4267 paramName
- pNameTable
, pTI
->pTypeLib
);
4269 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4273 pTI
->cFuncs
= cFuncs
;
4276 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4277 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4278 SLTG_TypeInfoTail
*pTITail
)
4281 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4283 if(pTIHeader
->href_table
!= 0xffffffff) {
4284 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4290 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4291 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4293 heap_free(ref_lookup
);
4297 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4298 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4299 const SLTG_TypeInfoTail
*pTITail
)
4302 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4304 if(pTIHeader
->href_table
!= 0xffffffff) {
4305 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4311 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4312 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4315 if (pTITail
->funcs_off
!= 0xffff)
4316 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4318 heap_free(ref_lookup
);
4320 if (TRACE_ON(typelib
))
4321 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4324 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4325 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4326 const SLTG_TypeInfoTail
*pTITail
)
4328 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4331 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4332 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4333 const SLTG_TypeInfoTail
*pTITail
)
4336 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4338 if (pTITail
->simple_alias
) {
4339 /* if simple alias, no more processing required */
4340 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4341 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4345 if(pTIHeader
->href_table
!= 0xffffffff) {
4346 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4350 /* otherwise it is an offset to a type */
4351 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4353 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4354 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4356 heap_free(ref_lookup
);
4359 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4360 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4361 const SLTG_TypeInfoTail
*pTITail
)
4363 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4364 if (pTIHeader
->href_table
!= 0xffffffff)
4365 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4368 if (pTITail
->vars_off
!= 0xffff)
4369 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4371 if (pTITail
->funcs_off
!= 0xffff)
4372 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4374 if (pTITail
->impls_off
!= 0xffff)
4375 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4377 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4378 * of dispinterface functions including the IDispatch ones, so
4379 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4380 pTI
->cbSizeVft
= pTI
->cFuncs
* pTI
->pTypeLib
->ptr_size
;
4382 heap_free(ref_lookup
);
4383 if (TRACE_ON(typelib
))
4384 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4387 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4388 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4389 const SLTG_TypeInfoTail
*pTITail
)
4391 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4394 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4395 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4396 const SLTG_TypeInfoTail
*pTITail
)
4398 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4399 if (pTIHeader
->href_table
!= 0xffffffff)
4400 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4403 if (pTITail
->vars_off
!= 0xffff)
4404 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4406 if (pTITail
->funcs_off
!= 0xffff)
4407 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4408 heap_free(ref_lookup
);
4409 if (TRACE_ON(typelib
))
4413 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4414 manageable copy of it into this */
4427 } SLTG_InternalOtherTypeInfo
;
4429 /****************************************************************************
4430 * ITypeLib2_Constructor_SLTG
4432 * loading a SLTG typelib from an in-memory image
4434 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4436 ITypeLibImpl
*pTypeLibImpl
;
4437 SLTG_Header
*pHeader
;
4438 SLTG_BlkEntry
*pBlkEntry
;
4442 LPVOID pBlk
, pFirstBlk
;
4443 SLTG_LibBlk
*pLibBlk
;
4444 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4445 char *pAfterOTIBlks
= NULL
;
4446 char *pNameTable
, *ptr
;
4449 ITypeInfoImpl
**ppTypeInfoImpl
;
4451 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4454 pTypeLibImpl
= TypeLibImpl_Constructor();
4455 if (!pTypeLibImpl
) return NULL
;
4459 TRACE_(typelib
)("header:\n");
4460 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4461 pHeader
->nrOfFileBlks
);
4462 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4463 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4464 pHeader
->SLTG_magic
);
4468 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4469 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4471 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4472 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4474 /* Next we have a magic block */
4475 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4477 /* Let's see if we're still in sync */
4478 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4479 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4480 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4483 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4484 sizeof(SLTG_DIR_MAGIC
))) {
4485 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4489 pIndex
= (SLTG_Index
*)(pMagic
+1);
4491 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4493 pFirstBlk
= pPad9
+ 1;
4495 /* We'll set up a ptr to the main library block, which is the last one. */
4497 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4498 pBlkEntry
[order
].next
!= 0;
4499 order
= pBlkEntry
[order
].next
- 1, i
++) {
4500 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4504 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4506 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4511 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4513 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4516 ptr
= (char*)pLibBlk
+ len
;
4518 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4522 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4524 w
= *(WORD
*)(ptr
+ 2);
4527 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4528 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4529 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4531 w
= *(WORD
*)(ptr
+ 4 + len
);
4533 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4535 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4536 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4537 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4539 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4540 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4541 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4543 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4544 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4547 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4548 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4549 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4550 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4551 len
+= sizeof(SLTG_OtherTypeInfo
);
4555 pAfterOTIBlks
= ptr
;
4557 /* Skip this WORD and get the next DWORD */
4558 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4560 /* Now add this to pLibBLk look at what we're pointing at and
4561 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4562 dust and we should be pointing at the beginning of the name
4565 pNameTable
= (char*)pLibBlk
+ len
;
4567 switch(*(WORD
*)pNameTable
) {
4574 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4578 pNameTable
+= 0x216;
4582 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4584 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4587 /* Hopefully we now have enough ptrs set up to actually read in
4588 some TypeInfos. It's not clear which order to do them in, so
4589 I'll just follow the links along the BlkEntry chain and read
4590 them in the order in which they are in the file */
4592 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4593 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4595 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4596 pBlkEntry
[order
].next
!= 0;
4597 order
= pBlkEntry
[order
].next
- 1, i
++) {
4599 SLTG_TypeInfoHeader
*pTIHeader
;
4600 SLTG_TypeInfoTail
*pTITail
;
4601 SLTG_MemberHeader
*pMemHeader
;
4603 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4604 FIXME_(typelib
)("Index strings don't match\n");
4605 heap_free(pOtherTypeInfoBlks
);
4610 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4611 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4612 heap_free(pOtherTypeInfoBlks
);
4615 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4616 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4617 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4619 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4620 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4621 (*ppTypeInfoImpl
)->index
= i
;
4622 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4623 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4624 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4625 (*ppTypeInfoImpl
)->typekind
= pTIHeader
->typekind
;
4626 (*ppTypeInfoImpl
)->wMajorVerNum
= pTIHeader
->major_version
;
4627 (*ppTypeInfoImpl
)->wMinorVerNum
= pTIHeader
->minor_version
;
4628 (*ppTypeInfoImpl
)->wTypeFlags
=
4629 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4631 if((*ppTypeInfoImpl
)->wTypeFlags
& TYPEFLAG_FDUAL
)
4632 (*ppTypeInfoImpl
)->typekind
= TKIND_DISPATCH
;
4634 if((pTIHeader
->typeflags1
& 7) != 2)
4635 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4636 if(pTIHeader
->typeflags3
!= 2)
4637 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4639 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4640 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4641 typekind_desc
[pTIHeader
->typekind
],
4642 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4643 (*ppTypeInfoImpl
)->wTypeFlags
);
4645 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4647 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4649 (*ppTypeInfoImpl
)->cbAlignment
= pTITail
->cbAlignment
;
4650 (*ppTypeInfoImpl
)->cbSizeInstance
= pTITail
->cbSizeInstance
;
4651 (*ppTypeInfoImpl
)->cbSizeVft
= pTITail
->cbSizeVft
;
4653 switch(pTIHeader
->typekind
) {
4655 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4656 pTIHeader
, pTITail
);
4660 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4661 pTIHeader
, pTITail
);
4664 case TKIND_INTERFACE
:
4665 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4666 pTIHeader
, pTITail
);
4670 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4671 pTIHeader
, pTITail
);
4675 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4676 pTIHeader
, pTITail
);
4679 case TKIND_DISPATCH
:
4680 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4681 pTIHeader
, pTITail
);
4685 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4686 pTIHeader
, pTITail
);
4690 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4695 /* could get cFuncs, cVars and cImplTypes from here
4696 but we've already set those */
4697 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4713 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4716 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4717 FIXME("Somehow processed %d TypeInfos\n", i
);
4718 heap_free(pOtherTypeInfoBlks
);
4722 heap_free(pOtherTypeInfoBlks
);
4723 return &pTypeLibImpl
->ITypeLib2_iface
;
4726 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4728 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4730 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4732 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4733 IsEqualIID(riid
,&IID_ITypeLib
)||
4734 IsEqualIID(riid
,&IID_ITypeLib2
))
4736 *ppv
= &This
->ITypeLib2_iface
;
4738 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4739 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4741 *ppv
= &This
->ICreateTypeLib2_iface
;
4746 TRACE("-- Interface: E_NOINTERFACE\n");
4747 return E_NOINTERFACE
;
4750 IUnknown_AddRef((IUnknown
*)*ppv
);
4754 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4756 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4757 ULONG ref
= InterlockedIncrement(&This
->ref
);
4759 TRACE("(%p) ref=%u\n", This
, ref
);
4764 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4766 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4767 ULONG ref
= InterlockedDecrement(&This
->ref
);
4769 TRACE("(%p) ref=%u\n",This
, ref
);
4773 TLBImpLib
*pImpLib
, *pImpLibNext
;
4774 TLBRefType
*ref_type
;
4775 TLBString
*tlbstr
, *tlbstr_next
;
4776 TLBGuid
*tlbguid
, *tlbguid_next
;
4780 /* remove cache entry */
4783 TRACE("removing from cache list\n");
4784 EnterCriticalSection(&cache_section
);
4785 if(This
->entry
.next
)
4786 list_remove(&This
->entry
);
4787 LeaveCriticalSection(&cache_section
);
4788 heap_free(This
->path
);
4790 TRACE(" destroying ITypeLib(%p)\n",This
);
4792 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4793 list_remove(&tlbstr
->entry
);
4794 SysFreeString(tlbstr
->str
);
4798 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4799 list_remove(&tlbstr
->entry
);
4800 SysFreeString(tlbstr
->str
);
4804 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4805 list_remove(&tlbguid
->entry
);
4809 TLB_FreeCustData(&This
->custdata_list
);
4811 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4812 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4813 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4815 heap_free(This
->pTypeDesc
);
4817 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4819 if (pImpLib
->pImpTypeLib
)
4820 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4821 SysFreeString(pImpLib
->name
);
4823 list_remove(&pImpLib
->entry
);
4827 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4829 list_remove(&ref_type
->entry
);
4830 heap_free(ref_type
);
4833 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4834 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4835 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4837 heap_free(This
->typeinfos
);
4845 /* ITypeLib::GetTypeInfoCount
4847 * Returns the number of type descriptions in the type library
4849 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4851 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4852 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4853 return This
->TypeInfoCount
;
4856 /* ITypeLib::GetTypeInfo
4858 * retrieves the specified type description in the library.
4860 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4863 ITypeInfo
**ppTInfo
)
4865 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4867 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4870 return E_INVALIDARG
;
4872 if(index
>= This
->TypeInfoCount
)
4873 return TYPE_E_ELEMENTNOTFOUND
;
4875 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4876 ITypeInfo_AddRef(*ppTInfo
);
4882 /* ITypeLibs::GetTypeInfoType
4884 * Retrieves the type of a type description.
4886 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4891 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4893 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4896 return E_INVALIDARG
;
4898 if(index
>= This
->TypeInfoCount
)
4899 return TYPE_E_ELEMENTNOTFOUND
;
4901 *pTKind
= This
->typeinfos
[index
]->typekind
;
4906 /* ITypeLib::GetTypeInfoOfGuid
4908 * Retrieves the type description that corresponds to the specified GUID.
4911 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4914 ITypeInfo
**ppTInfo
)
4916 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4919 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4921 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4922 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4923 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4924 ITypeInfo_AddRef(*ppTInfo
);
4929 return TYPE_E_ELEMENTNOTFOUND
;
4932 /* ITypeLib::GetLibAttr
4934 * Retrieves the structure that contains the library's attributes.
4937 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4941 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4943 TRACE("(%p, %p)\n", This
, attr
);
4945 if (!attr
) return E_INVALIDARG
;
4947 *attr
= heap_alloc(sizeof(**attr
));
4948 if (!*attr
) return E_OUTOFMEMORY
;
4950 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4951 (*attr
)->lcid
= This
->set_lcid
;
4952 (*attr
)->syskind
= This
->syskind
;
4953 (*attr
)->wMajorVerNum
= This
->ver_major
;
4954 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4955 (*attr
)->wLibFlags
= This
->libflags
;
4960 /* ITypeLib::GetTypeComp
4962 * Enables a client compiler to bind to a library's types, variables,
4963 * constants, and global functions.
4966 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4968 ITypeComp
**ppTComp
)
4970 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4972 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4973 *ppTComp
= &This
->ITypeComp_iface
;
4974 ITypeComp_AddRef(*ppTComp
);
4979 /* ITypeLib::GetDocumentation
4981 * Retrieves the library's documentation string, the complete Help file name
4982 * and path, and the context identifier for the library Help topic in the Help
4985 * On a successful return all non-null BSTR pointers will have been set,
4988 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4992 BSTR
*pBstrDocString
,
4993 DWORD
*pdwHelpContext
,
4994 BSTR
*pBstrHelpFile
)
4996 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4997 HRESULT result
= E_INVALIDARG
;
5000 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
5002 pBstrName
, pBstrDocString
,
5003 pdwHelpContext
, pBstrHelpFile
);
5007 /* documentation for the typelib */
5012 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
5020 if (This
->DocString
)
5022 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
5026 *pBstrDocString
= NULL
;
5030 *pdwHelpContext
= This
->dwHelpContext
;
5036 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5040 *pBstrHelpFile
= NULL
;
5047 /* for a typeinfo */
5048 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5050 if(SUCCEEDED(result
))
5052 result
= ITypeInfo_GetDocumentation(pTInfo
,
5056 pdwHelpContext
, pBstrHelpFile
);
5058 ITypeInfo_Release(pTInfo
);
5063 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5065 if (pBstrName
) SysFreeString (*pBstrName
);
5067 return STG_E_INSUFFICIENTMEMORY
;
5072 * Indicates whether a passed-in string contains the name of a type or member
5073 * described in the library.
5076 static HRESULT WINAPI
ITypeLib2_fnIsName(
5082 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5084 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5086 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5090 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5091 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5092 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5093 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5094 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5096 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5097 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5098 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5099 goto ITypeLib2_fnIsName_exit
;
5102 for(vrc
= 0; vrc
< pTInfo
->cVars
; ++vrc
){
5103 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5104 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5110 ITypeLib2_fnIsName_exit
:
5111 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5112 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5117 /* ITypeLib::FindName
5119 * Finds occurrences of a type description in a type library. This may be used
5120 * to quickly verify that a name exists in a type library.
5123 static HRESULT WINAPI
ITypeLib2_fnFindName(
5127 ITypeInfo
**ppTInfo
,
5131 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5136 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5138 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5139 return E_INVALIDARG
;
5141 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5142 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5143 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5147 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5148 memid
[count
] = MEMBERID_NIL
;
5149 goto ITypeLib2_fnFindName_exit
;
5152 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5153 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5155 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5156 memid
[count
] = func
->funcdesc
.memid
;
5157 goto ITypeLib2_fnFindName_exit
;
5161 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->cVars
, name
);
5163 memid
[count
] = var
->vardesc
.memid
;
5164 goto ITypeLib2_fnFindName_exit
;
5168 ITypeLib2_fnFindName_exit
:
5169 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5170 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5173 TRACE("found %d typeinfos\n", count
);
5180 /* ITypeLib::ReleaseTLibAttr
5182 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5185 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5187 TLIBATTR
*pTLibAttr
)
5189 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5190 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5191 heap_free(pTLibAttr
);
5194 /* ITypeLib2::GetCustData
5196 * gets the custom data
5198 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5203 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5204 TLBCustData
*pCData
;
5206 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5208 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5210 return TYPE_E_ELEMENTNOTFOUND
;
5212 VariantInit(pVarVal
);
5213 VariantCopy(pVarVal
, &pCData
->data
);
5218 /* ITypeLib2::GetLibStatistics
5220 * Returns statistics about a type library that are required for efficient
5221 * sizing of hash tables.
5224 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5226 ULONG
*pcUniqueNames
,
5227 ULONG
*pcchUniqueNames
)
5229 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5231 FIXME("(%p): stub!\n", This
);
5233 if(pcUniqueNames
) *pcUniqueNames
=1;
5234 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5238 /* ITypeLib2::GetDocumentation2
5240 * Retrieves the library's documentation string, the complete Help file name
5241 * and path, the localization context to use, and the context ID for the
5242 * library Help topic in the Help file.
5245 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5249 BSTR
*pbstrHelpString
,
5250 DWORD
*pdwHelpStringContext
,
5251 BSTR
*pbstrHelpStringDll
)
5253 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5257 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5259 /* the help string should be obtained from the helpstringdll,
5260 * using the _DLLGetDocumentation function, based on the supplied
5261 * lcid. Nice to do sometime...
5265 /* documentation for the typelib */
5267 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5268 if(pdwHelpStringContext
)
5269 *pdwHelpStringContext
=This
->dwHelpContext
;
5270 if(pbstrHelpStringDll
)
5271 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5277 /* for a typeinfo */
5278 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5280 if(SUCCEEDED(result
))
5282 ITypeInfo2
* pTInfo2
;
5283 result
= ITypeInfo_QueryInterface(pTInfo
,
5285 (LPVOID
*) &pTInfo2
);
5287 if(SUCCEEDED(result
))
5289 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5293 pdwHelpStringContext
,
5294 pbstrHelpStringDll
);
5296 ITypeInfo2_Release(pTInfo2
);
5299 ITypeInfo_Release(pTInfo
);
5305 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5307 TLBCustData
*pCData
;
5311 ct
= list_count(custdata_list
);
5313 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5314 if(!pCustData
->prgCustData
)
5315 return E_OUTOFMEMORY
;
5317 pCustData
->cCustData
= ct
;
5319 cdi
= pCustData
->prgCustData
;
5320 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5321 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5322 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5330 /* ITypeLib2::GetAllCustData
5332 * Gets all custom data items for the library.
5335 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5337 CUSTDATA
*pCustData
)
5339 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5340 TRACE("(%p)->(%p)\n", This
, pCustData
);
5341 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5344 static const ITypeLib2Vtbl tlbvt
= {
5345 ITypeLib2_fnQueryInterface
,
5347 ITypeLib2_fnRelease
,
5348 ITypeLib2_fnGetTypeInfoCount
,
5349 ITypeLib2_fnGetTypeInfo
,
5350 ITypeLib2_fnGetTypeInfoType
,
5351 ITypeLib2_fnGetTypeInfoOfGuid
,
5352 ITypeLib2_fnGetLibAttr
,
5353 ITypeLib2_fnGetTypeComp
,
5354 ITypeLib2_fnGetDocumentation
,
5356 ITypeLib2_fnFindName
,
5357 ITypeLib2_fnReleaseTLibAttr
,
5359 ITypeLib2_fnGetCustData
,
5360 ITypeLib2_fnGetLibStatistics
,
5361 ITypeLib2_fnGetDocumentation2
,
5362 ITypeLib2_fnGetAllCustData
5366 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5368 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5370 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5373 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5375 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5377 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5380 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5382 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5384 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5387 static HRESULT WINAPI
ITypeLibComp_fnBind(
5392 ITypeInfo
** ppTInfo
,
5393 DESCKIND
* pDescKind
,
5396 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5397 BOOL typemismatch
= FALSE
;
5400 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5402 *pDescKind
= DESCKIND_NONE
;
5403 pBindPtr
->lptcomp
= NULL
;
5406 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5407 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5408 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5410 /* FIXME: check wFlags here? */
5411 /* FIXME: we should use a hash table to look this info up using lHash
5412 * instead of an O(n) search */
5413 if ((pTypeInfo
->typekind
== TKIND_ENUM
) ||
5414 (pTypeInfo
->typekind
== TKIND_MODULE
))
5416 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5418 *pDescKind
= DESCKIND_TYPECOMP
;
5419 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5420 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5421 TRACE("module or enum: %s\n", debugstr_w(szName
));
5426 if ((pTypeInfo
->typekind
== TKIND_MODULE
) ||
5427 (pTypeInfo
->typekind
== TKIND_ENUM
))
5429 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5432 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5433 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5435 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5438 else if (hr
== TYPE_E_TYPEMISMATCH
)
5439 typemismatch
= TRUE
;
5442 if ((pTypeInfo
->typekind
== TKIND_COCLASS
) &&
5443 (pTypeInfo
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5445 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5447 ITypeInfo
*subtypeinfo
;
5449 DESCKIND subdesckind
;
5451 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5452 &subtypeinfo
, &subdesckind
, &subbindptr
);
5453 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5455 TYPEDESC tdesc_appobject
;
5456 const VARDESC vardesc_appobject
=
5459 NULL
, /* lpstrSchema */
5474 VAR_STATIC
/* varkind */
5477 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5478 tdesc_appobject
.vt
= VT_USERDEFINED
;
5480 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5482 /* cleanup things filled in by Bind call so we can put our
5483 * application object data in there instead */
5484 switch (subdesckind
)
5486 case DESCKIND_FUNCDESC
:
5487 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5489 case DESCKIND_VARDESC
:
5490 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5495 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5497 if (pTypeInfo
->hreftype
== -1)
5498 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5500 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5504 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5505 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5506 ITypeInfo_AddRef(*ppTInfo
);
5509 else if (hr
== TYPE_E_TYPEMISMATCH
)
5510 typemismatch
= TRUE
;
5516 TRACE("type mismatch %s\n", debugstr_w(szName
));
5517 return TYPE_E_TYPEMISMATCH
;
5521 TRACE("name not found %s\n", debugstr_w(szName
));
5526 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5530 ITypeInfo
** ppTInfo
,
5531 ITypeComp
** ppTComp
)
5533 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5534 ITypeInfoImpl
*info
;
5536 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5538 if(!szName
|| !ppTInfo
|| !ppTComp
)
5539 return E_INVALIDARG
;
5541 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5548 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5549 ITypeInfo_AddRef(*ppTInfo
);
5550 *ppTComp
= &info
->ITypeComp_iface
;
5551 ITypeComp_AddRef(*ppTComp
);
5556 static const ITypeCompVtbl tlbtcvt
=
5559 ITypeLibComp_fnQueryInterface
,
5560 ITypeLibComp_fnAddRef
,
5561 ITypeLibComp_fnRelease
,
5563 ITypeLibComp_fnBind
,
5564 ITypeLibComp_fnBindType
5567 /*================== ITypeInfo(2) Methods ===================================*/
5568 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5570 ITypeInfoImpl
*pTypeInfoImpl
;
5572 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5575 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5576 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5577 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5578 pTypeInfoImpl
->ref
= 0;
5579 pTypeInfoImpl
->hreftype
= -1;
5580 pTypeInfoImpl
->memidConstructor
= MEMBERID_NIL
;
5581 pTypeInfoImpl
->memidDestructor
= MEMBERID_NIL
;
5582 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5583 list_init(pTypeInfoImpl
->pcustdata_list
);
5585 TRACE("(%p)\n", pTypeInfoImpl
);
5586 return pTypeInfoImpl
;
5589 /* ITypeInfo::QueryInterface
5591 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5596 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5598 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5601 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5602 IsEqualIID(riid
,&IID_ITypeInfo
)||
5603 IsEqualIID(riid
,&IID_ITypeInfo2
))
5605 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5606 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5607 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5610 ITypeInfo2_AddRef(iface
);
5611 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5614 TRACE("-- Interface: E_NOINTERFACE\n");
5615 return E_NOINTERFACE
;
5618 /* ITypeInfo::AddRef
5620 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5622 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5623 ULONG ref
= InterlockedIncrement(&This
->ref
);
5625 TRACE("(%p)->ref is %u\n",This
, ref
);
5627 if (ref
== 1 /* incremented from 0 */)
5628 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5633 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5637 TRACE("destroying ITypeInfo(%p)\n",This
);
5639 for (i
= 0; i
< This
->cFuncs
; ++i
)
5642 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5643 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5645 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5646 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5647 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5648 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5650 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5651 heap_free(pFInfo
->pParamDesc
);
5652 TLB_FreeCustData(&pFInfo
->custdata_list
);
5654 heap_free(This
->funcdescs
);
5656 for(i
= 0; i
< This
->cVars
; ++i
)
5658 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5659 if (pVInfo
->vardesc_create
) {
5660 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5661 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5662 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5663 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5665 TLB_FreeCustData(&pVInfo
->custdata_list
);
5667 heap_free(This
->vardescs
);
5669 if(This
->impltypes
){
5670 for (i
= 0; i
< This
->cImplTypes
; ++i
){
5671 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5672 TLB_FreeCustData(&pImpl
->custdata_list
);
5674 heap_free(This
->impltypes
);
5677 TLB_FreeCustData(&This
->custdata_list
);
5682 /* ITypeInfo::Release
5684 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5686 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5687 ULONG ref
= InterlockedDecrement(&This
->ref
);
5689 TRACE("(%p)->(%u)\n",This
, ref
);
5693 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5694 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5695 if (not_attached_to_typelib
)
5697 /* otherwise This will be freed when typelib is freed */
5703 /* ITypeInfo::GetTypeAttr
5705 * Retrieves a TYPEATTR structure that contains the attributes of the type
5709 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5710 LPTYPEATTR
*ppTypeAttr
)
5712 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5715 TRACE("(%p)\n",This
);
5717 size
= sizeof(**ppTypeAttr
);
5718 if (This
->typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5719 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5721 *ppTypeAttr
= heap_alloc(size
);
5723 return E_OUTOFMEMORY
;
5725 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5726 (*ppTypeAttr
)->lcid
= This
->lcid
;
5727 (*ppTypeAttr
)->memidConstructor
= This
->memidConstructor
;
5728 (*ppTypeAttr
)->memidDestructor
= This
->memidDestructor
;
5729 (*ppTypeAttr
)->lpstrSchema
= This
->lpstrSchema
;
5730 (*ppTypeAttr
)->cbSizeInstance
= This
->cbSizeInstance
;
5731 (*ppTypeAttr
)->typekind
= This
->typekind
;
5732 (*ppTypeAttr
)->cFuncs
= This
->cFuncs
;
5733 (*ppTypeAttr
)->cVars
= This
->cVars
;
5734 (*ppTypeAttr
)->cImplTypes
= This
->cImplTypes
;
5735 (*ppTypeAttr
)->cbSizeVft
= This
->cbSizeVft
;
5736 (*ppTypeAttr
)->cbAlignment
= This
->cbAlignment
;
5737 (*ppTypeAttr
)->wTypeFlags
= This
->wTypeFlags
;
5738 (*ppTypeAttr
)->wMajorVerNum
= This
->wMajorVerNum
;
5739 (*ppTypeAttr
)->wMinorVerNum
= This
->wMinorVerNum
;
5740 (*ppTypeAttr
)->idldescType
= This
->idldescType
;
5742 if (This
->tdescAlias
)
5743 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5744 This
->tdescAlias
, *ppTypeAttr
+ 1);
5746 (*ppTypeAttr
)->tdescAlias
.vt
= VT_EMPTY
;
5747 (*ppTypeAttr
)->tdescAlias
.u
.lptdesc
= NULL
;
5750 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5751 /* This should include all the inherited funcs */
5752 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5753 /* This is always the size of IDispatch's vtbl */
5754 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5755 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5760 /* ITypeInfo::GetTypeComp
5762 * Retrieves the ITypeComp interface for the type description, which enables a
5763 * client compiler to bind to the type description's members.
5766 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5767 ITypeComp
* *ppTComp
)
5769 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5771 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5773 *ppTComp
= &This
->ITypeComp_iface
;
5774 ITypeComp_AddRef(*ppTComp
);
5778 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5780 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5781 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5782 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5786 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5789 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5790 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5792 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5793 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5794 *buffer
+= sizeof(PARAMDESCEX
);
5795 *pparamdescex_dest
= *pparamdescex_src
;
5796 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5797 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5798 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5799 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5802 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5806 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5808 UINT len
= SysStringLen(str
), i
;
5809 for (i
= 0; i
< len
; ++i
)
5815 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5817 if (V_VT(var
) == VT_INT
)
5818 return VariantChangeType(var
, var
, 0, VT_I4
);
5819 else if (V_VT(var
) == VT_UINT
)
5820 return VariantChangeType(var
, var
, 0, VT_UI4
);
5821 else if (V_VT(var
) == VT_BSTR
)
5822 return TLB_SanitizeBSTR(V_BSTR(var
));
5827 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5829 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5830 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5833 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5837 SIZE_T size
= sizeof(*src
);
5841 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5842 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5843 for (i
= 0; i
< src
->cParams
; i
++)
5845 size
+= sizeof(ELEMDESC
);
5846 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5849 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5850 if (!dest
) return E_OUTOFMEMORY
;
5853 if (dispinterface
) /* overwrite funckind */
5854 dest
->funckind
= FUNC_DISPATCH
;
5855 buffer
= (char *)(dest
+ 1);
5857 dest
->oVft
= dest
->oVft
& 0xFFFC;
5859 if (dest
->cScodes
) {
5860 dest
->lprgscode
= (SCODE
*)buffer
;
5861 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5862 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5864 dest
->lprgscode
= NULL
;
5866 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5869 SysFreeString((BSTR
)dest
);
5873 if (dest
->cParams
) {
5874 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5875 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5876 for (i
= 0; i
< src
->cParams
; i
++)
5878 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5884 /* undo the above actions */
5885 for (i
= i
- 1; i
>= 0; i
--)
5886 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5887 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5888 SysFreeString((BSTR
)dest
);
5892 dest
->lprgelemdescParam
= NULL
;
5894 /* special treatment for dispinterfaces: this makes functions appear
5895 * to return their [retval] value when it is really returning an
5897 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5899 if (dest
->cParams
&&
5900 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5902 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5903 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5905 ERR("elemdesc should have started with VT_PTR instead of:\n");
5907 dump_ELEMDESC(elemdesc
);
5908 return E_UNEXPECTED
;
5911 /* copy last parameter to the return value. we are using a flat
5912 * buffer so there is no danger of leaking memory in
5914 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5916 /* remove the last parameter */
5920 /* otherwise this function is made to appear to have no return
5922 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5930 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5932 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5933 if (var_desc
->varkind
== VAR_CONST
)
5934 VariantClear(var_desc
->u
.lpvarValue
);
5935 SysFreeString((BSTR
)var_desc
);
5938 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5940 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5942 if (index
>= This
->cFuncs
)
5943 return TYPE_E_ELEMENTNOTFOUND
;
5945 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5949 /* internal function to make the inherited interfaces' methods appear
5950 * part of the interface */
5951 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5952 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5954 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5956 UINT implemented_funcs
= 0;
5961 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5965 ITypeInfo
*pSubTypeInfo
;
5968 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5972 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5975 &sub_funcs
, hrefoffset
);
5976 implemented_funcs
+= sub_funcs
;
5977 ITypeInfo_Release(pSubTypeInfo
);
5980 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5984 *funcs
= implemented_funcs
+ This
->cFuncs
;
5988 if (index
< implemented_funcs
)
5989 return E_INVALIDARG
;
5990 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5994 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5996 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5999 switch (pTypeDesc
->vt
)
6001 case VT_USERDEFINED
:
6002 pTypeDesc
->u
.hreftype
+= hrefoffset
;
6006 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
6009 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
6017 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
6020 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6021 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
6022 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
6025 /* ITypeInfo::GetFuncDesc
6027 * Retrieves the FUNCDESC structure that contains information about a
6028 * specified function.
6031 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
6032 LPFUNCDESC
*ppFuncDesc
)
6034 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6035 const FUNCDESC
*internal_funcdesc
;
6037 UINT hrefoffset
= 0;
6039 TRACE("(%p) index %d\n", This
, index
);
6042 return E_INVALIDARG
;
6044 if (This
->needs_layout
)
6045 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6047 if (This
->typekind
== TKIND_DISPATCH
)
6048 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
6049 &internal_funcdesc
, NULL
,
6052 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6053 &internal_funcdesc
);
6056 WARN("description for function %d not found\n", index
);
6060 hr
= TLB_AllocAndInitFuncDesc(
6063 This
->typekind
== TKIND_DISPATCH
);
6065 if ((This
->typekind
== TKIND_DISPATCH
) && hrefoffset
)
6066 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6068 TRACE("-- 0x%08x\n", hr
);
6072 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6076 SIZE_T size
= sizeof(*src
);
6079 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6080 if (src
->varkind
== VAR_CONST
)
6081 size
+= sizeof(VARIANT
);
6082 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6084 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6085 if (!dest
) return E_OUTOFMEMORY
;
6088 buffer
= (char *)(dest
+ 1);
6089 if (src
->lpstrSchema
)
6092 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6093 len
= strlenW(src
->lpstrSchema
);
6094 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6095 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6098 if (src
->varkind
== VAR_CONST
)
6102 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6103 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6104 buffer
+= sizeof(VARIANT
);
6105 VariantInit(dest
->u
.lpvarValue
);
6106 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6109 SysFreeString((BSTR
)dest
);
6113 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6116 if (src
->varkind
== VAR_CONST
)
6117 VariantClear(dest
->u
.lpvarValue
);
6118 SysFreeString((BSTR
)dest
);
6125 /* ITypeInfo::GetVarDesc
6127 * Retrieves a VARDESC structure that describes the specified variable.
6130 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6131 LPVARDESC
*ppVarDesc
)
6133 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6134 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6136 TRACE("(%p) index %d\n", This
, index
);
6138 if(index
>= This
->cVars
)
6139 return TYPE_E_ELEMENTNOTFOUND
;
6141 if (This
->needs_layout
)
6142 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6144 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6147 /* ITypeInfo_GetNames
6149 * Retrieves the variable with the specified member ID (or the name of the
6150 * property or method and its parameters) that correspond to the specified
6153 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6154 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6156 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6157 const TLBFuncDesc
*pFDesc
;
6158 const TLBVarDesc
*pVDesc
;
6160 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6163 return E_INVALIDARG
;
6167 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
6170 if(!cMaxNames
|| !pFDesc
->Name
)
6173 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6176 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6177 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6179 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6185 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
6188 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6193 if(This
->impltypes
&&
6194 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
6195 /* recursive search */
6198 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6199 if(SUCCEEDED(result
))
6201 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6202 ITypeInfo_Release(pTInfo
);
6205 WARN("Could not search inherited interface!\n");
6209 WARN("no names found\n");
6212 return TYPE_E_ELEMENTNOTFOUND
;
6218 /* ITypeInfo::GetRefTypeOfImplType
6220 * If a type description describes a COM class, it retrieves the type
6221 * description of the implemented interface types. For an interface,
6222 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6226 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6231 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6234 TRACE("(%p) index %d\n", This
, index
);
6235 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6239 /* only valid on dual interfaces;
6240 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6243 if (This
->wTypeFlags
& TYPEFLAG_FDUAL
)
6249 hr
= TYPE_E_ELEMENTNOTFOUND
;
6252 else if(index
== 0 && This
->typekind
== TKIND_DISPATCH
)
6254 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6255 *pRefType
= This
->pTypeLib
->dispatch_href
;
6259 if(index
>= This
->cImplTypes
)
6260 hr
= TYPE_E_ELEMENTNOTFOUND
;
6262 *pRefType
= This
->impltypes
[index
].hRef
;
6263 if(This
->typekind
== TKIND_INTERFACE
)
6271 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6273 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6279 /* ITypeInfo::GetImplTypeFlags
6281 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6282 * or base interface in a type description.
6284 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6285 UINT index
, INT
*pImplTypeFlags
)
6287 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6289 TRACE("(%p) index %d\n", This
, index
);
6292 return E_INVALIDARG
;
6294 if(This
->typekind
== TKIND_DISPATCH
&& index
== 0){
6295 *pImplTypeFlags
= 0;
6299 if(index
>= This
->cImplTypes
)
6300 return TYPE_E_ELEMENTNOTFOUND
;
6302 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6308 * Maps between member names and member IDs, and parameter names and
6311 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6312 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6314 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6315 const TLBVarDesc
*pVDesc
;
6319 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6322 /* init out parameters in case of failure */
6323 for (i
= 0; i
< cNames
; i
++)
6324 pMemId
[i
] = MEMBERID_NIL
;
6326 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
) {
6328 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6329 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6330 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6331 for(i
=1; i
< cNames
; i
++){
6332 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6333 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6335 if( j
<pFDesc
->funcdesc
.cParams
)
6338 ret
=DISP_E_UNKNOWNNAME
;
6340 TRACE("-- 0x%08x\n", ret
);
6344 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, *rgszNames
);
6347 *pMemId
= pVDesc
->vardesc
.memid
;
6350 /* not found, see if it can be found in an inherited interface */
6351 if(This
->impltypes
) {
6352 /* recursive search */
6354 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6356 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6357 ITypeInfo_Release(pTInfo
);
6360 WARN("Could not search inherited interface!\n");
6362 WARN("no names found\n");
6363 return DISP_E_UNKNOWNNAME
;
6369 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6370 __ASM_GLOBAL_FUNC( call_method
,
6372 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6373 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6374 "movl %esp,%ebp\n\t"
6375 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6377 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6379 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6380 "movl 12(%ebp),%edx\n\t"
6381 "movl %esp,%edi\n\t"
6384 "subl %edx,%edi\n\t"
6385 "andl $~15,%edi\n\t"
6386 "movl %edi,%esp\n\t"
6387 "movl 12(%ebp),%ecx\n\t"
6388 "movl 16(%ebp),%esi\n\t"
6391 "1:\tcall *8(%ebp)\n\t"
6392 "subl %esp,%edi\n\t"
6393 "movl 20(%ebp),%ecx\n\t"
6394 "movl %edi,(%ecx)\n\t"
6395 "leal -8(%ebp),%esp\n\t"
6397 __ASM_CFI(".cfi_same_value %edi\n\t")
6399 __ASM_CFI(".cfi_same_value %esi\n\t")
6401 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6402 __ASM_CFI(".cfi_same_value %ebp\n\t")
6405 /* same function but returning floating point */
6406 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6408 /* ITypeInfo::Invoke
6410 * Invokes a method, or accesses a property of an object, that implements the
6411 * interface described by the type description.
6414 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6418 if (TRACE_ON(ole
)) {
6420 TRACE("Calling %p(",func
);
6421 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6422 if (nrargs
> 30) TRACE("...");
6429 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6432 FIXME("unsupported calling convention %d\n",callconv
);
6436 TRACE("returns %08x\n",res
);
6440 #elif defined(__x86_64__)
6442 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6443 __ASM_GLOBAL_FUNC( call_method
,
6445 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6446 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6447 "movq %rsp,%rbp\n\t"
6448 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6450 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6452 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6453 "movq %rcx,%rax\n\t"
6456 "cmovgq %rdx,%rcx\n\t"
6457 "leaq 0(,%rcx,8),%rdx\n\t"
6458 "subq %rdx,%rsp\n\t"
6459 "andq $~15,%rsp\n\t"
6460 "movq %rsp,%rdi\n\t"
6463 "movq 0(%rsp),%rcx\n\t"
6464 "movq 8(%rsp),%rdx\n\t"
6465 "movq 16(%rsp),%r8\n\t"
6466 "movq 24(%rsp),%r9\n\t"
6467 "movq %rcx,%xmm0\n\t"
6468 "movq %rdx,%xmm1\n\t"
6469 "movq %r8,%xmm2\n\t"
6470 "movq %r9,%xmm3\n\t"
6472 "leaq -16(%rbp),%rsp\n\t"
6474 __ASM_CFI(".cfi_same_value %rdi\n\t")
6476 __ASM_CFI(".cfi_same_value %rsi\n\t")
6477 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6479 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6480 __ASM_CFI(".cfi_same_value %rbp\n\t")
6483 /* same function but returning floating point */
6484 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6486 #endif /* __x86_64__ */
6488 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6491 ITypeInfo
*tinfo2
= NULL
;
6492 TYPEATTR
*tattr
= NULL
;
6494 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6497 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6499 tdesc
->u
.hreftype
, hr
);
6502 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6505 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6506 ITypeInfo_Release(tinfo2
);
6510 switch (tattr
->typekind
)
6517 tdesc
= &tattr
->tdescAlias
;
6518 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6521 case TKIND_INTERFACE
:
6522 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6528 case TKIND_DISPATCH
:
6537 FIXME("TKIND_RECORD unhandled.\n");
6542 FIXME("TKIND_UNION unhandled.\n");
6547 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6551 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6552 ITypeInfo_Release(tinfo2
);
6556 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6560 /* enforce only one level of pointer indirection */
6561 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6563 tdesc
= tdesc
->u
.lptdesc
;
6565 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6566 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6567 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6568 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6569 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6571 VARTYPE vt_userdefined
= 0;
6572 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6573 if (tdesc
->vt
== VT_PTR
)
6575 vt_userdefined
= VT_BYREF
;
6576 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6578 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6580 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6581 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6583 *vt
|= vt_userdefined
;
6595 case VT_USERDEFINED
:
6596 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6603 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6604 hr
= DISP_E_BADVARTYPE
;
6608 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6623 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6629 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6633 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6635 ITypeInfo_Release(tinfo2
);
6639 switch(tattr
->typekind
) {
6641 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6644 case TKIND_INTERFACE
:
6645 case TKIND_DISPATCH
:
6646 *guid
= tattr
->guid
;
6650 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6651 hres
= E_UNEXPECTED
;
6654 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6655 ITypeInfo_Release(tinfo2
);
6659 /***********************************************************************
6660 * DispCallFunc (OLEAUT32.@)
6662 * Invokes a function of the specified calling convention, passing the
6663 * specified arguments and returns the result.
6666 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6667 * oVft [I] The offset in the vtable. See notes.
6668 * cc [I] Calling convention of the function to call.
6669 * vtReturn [I] The return type of the function.
6670 * cActuals [I] Number of parameters.
6671 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6672 * prgpvarg [I] The arguments to pass.
6673 * pvargResult [O] The return value of the function. Can be NULL.
6677 * Failure: HRESULT code.
6680 * The HRESULT return value of this function is not affected by the return
6681 * value of the user supplied function, which is returned in pvargResult.
6683 * If pvInstance is NULL then a non-object function is to be called and oVft
6684 * is the address of the function to call.
6686 * The cc parameter can be one of the following values:
6699 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6700 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6703 int argspos
, stack_offset
;
6708 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6709 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6710 pvargResult
, V_VT(pvargResult
));
6712 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6714 FIXME("unsupported calling convention %d\n",cc
);
6715 return E_INVALIDARG
;
6718 /* maximum size for an argument is sizeof(VARIANT) */
6719 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6721 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6725 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6726 func
= vtable
[oVft
/sizeof(void *)];
6727 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6729 else func
= (void *)oVft
;
6731 for (i
= 0; i
< cActuals
; i
++)
6733 VARIANT
*arg
= prgpvarg
[i
];
6744 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6745 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6749 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6750 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6752 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6753 args
[argspos
++] = V_BOOL(arg
);
6756 args
[argspos
++] = V_UI4(arg
);
6759 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6765 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6768 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6772 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6776 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6777 call_method( func
, argspos
, args
, &stack_offset
);
6782 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6785 WARN("invalid return type %u\n", vtReturn
);
6787 return E_INVALIDARG
;
6789 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6793 if (stack_offset
&& cc
== CC_STDCALL
)
6795 WARN( "stack pointer off by %d\n", stack_offset
);
6796 return DISP_E_BADCALLEE
;
6798 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6799 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6802 #elif defined(__x86_64__)
6808 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6809 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6810 pvargResult
, V_VT(pvargResult
));
6812 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6814 FIXME("unsupported calling convention %d\n",cc
);
6815 return E_INVALIDARG
;
6818 /* maximum size for an argument is sizeof(DWORD_PTR) */
6819 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6821 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6825 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6826 func
= vtable
[oVft
/sizeof(void *)];
6827 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6829 else func
= (void *)oVft
;
6831 for (i
= 0; i
< cActuals
; i
++)
6833 VARIANT
*arg
= prgpvarg
[i
];
6839 args
[argspos
++] = (ULONG_PTR
)arg
;
6841 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6842 args
[argspos
++] = V_BOOL(arg
);
6845 args
[argspos
++] = V_UI8(arg
);
6848 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6854 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6858 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6862 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6863 call_method( func
, argspos
, args
);
6866 WARN("invalid return type %u\n", vtReturn
);
6868 return E_INVALIDARG
;
6870 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6874 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6875 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6879 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6880 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6885 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6887 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6890 #define INVBUF_ELEMENT_SIZE \
6891 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6892 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6893 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6894 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6895 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6896 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6897 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6898 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6900 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6905 DISPPARAMS
*pDispParams
,
6906 VARIANT
*pVarResult
,
6907 EXCEPINFO
*pExcepInfo
,
6910 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6912 unsigned int var_index
;
6915 const TLBFuncDesc
*pFuncInfo
;
6918 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6919 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6922 if( This
->wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6923 return DISP_E_MEMBERNOTFOUND
;
6927 ERR("NULL pDispParams not allowed\n");
6928 return E_INVALIDARG
;
6931 dump_DispParms(pDispParams
);
6933 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6935 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6936 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6937 return E_INVALIDARG
;
6940 /* we do this instead of using GetFuncDesc since it will return a fake
6941 * FUNCDESC for dispinterfaces and we want the real function description */
6942 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
6943 pFuncInfo
= &This
->funcdescs
[fdc
];
6944 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6945 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6946 !func_restricted( &pFuncInfo
->funcdesc
))
6950 if (fdc
< This
->cFuncs
) {
6951 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6955 TRACE("invoking:\n");
6956 dump_TLBFuncDescOne(pFuncInfo
);
6959 switch (func_desc
->funckind
) {
6960 case FUNC_PUREVIRTUAL
:
6961 case FUNC_VIRTUAL
: {
6962 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6964 VARIANT retval
; /* pointer for storing byref retvals in */
6965 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6966 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6967 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6968 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6969 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6970 UINT vargs_converted
=0;
6974 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6976 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6978 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6979 hres
= DISP_E_PARAMNOTFOUND
;
6984 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6986 ERR("functions with the vararg attribute do not support named arguments\n");
6987 hres
= DISP_E_NONAMEDARGS
;
6991 for (i
= 0; i
< func_desc
->cParams
; i
++)
6993 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6994 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6999 TRACE("changing args\n");
7000 for (i
= 0; i
< func_desc
->cParams
; i
++)
7002 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7003 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7004 VARIANTARG
*src_arg
;
7006 if (wParamFlags
& PARAMFLAG_FLCID
)
7009 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7011 V_I4(arg
) = This
->pTypeLib
->lcid
;
7020 for (j
= 0; j
< cNamedArgs
; j
++)
7021 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7023 src_arg
= &pDispParams
->rgvarg
[j
];
7028 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7030 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7034 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7036 /* under most conditions the caller is not allowed to
7037 * pass in a dispparam arg in the index of what would be
7038 * the retval parameter. however, there is an exception
7039 * where the extra parameter is used in an extra
7040 * IDispatch::Invoke below */
7041 if ((i
< pDispParams
->cArgs
) &&
7042 ((func_desc
->cParams
!= 1) || !pVarResult
||
7043 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7045 hres
= DISP_E_BADPARAMCOUNT
;
7049 /* note: this check is placed so that if the caller passes
7050 * in a VARIANTARG for the retval we just ignore it, like
7052 if (i
== func_desc
->cParams
- 1)
7055 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7056 memset(arg
, 0, sizeof(*arg
));
7057 V_VT(arg
) = rgvt
[i
];
7058 memset(&retval
, 0, sizeof(retval
));
7059 V_BYREF(arg
) = &retval
;
7063 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7064 hres
= E_UNEXPECTED
;
7070 TRACE("%s\n", debugstr_variant(src_arg
));
7072 if(rgvt
[i
]!=V_VT(src_arg
))
7074 if (rgvt
[i
] == VT_VARIANT
)
7075 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7076 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7078 if (rgvt
[i
] == V_VT(src_arg
))
7079 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7082 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7083 if (wParamFlags
& PARAMFLAG_FIN
)
7084 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7085 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7087 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7089 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
7092 SAFEARRAYBOUND bound
;
7096 bound
.cElements
= pDispParams
->cArgs
-i
;
7097 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7099 ERR("SafeArrayCreate failed\n");
7102 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7105 ERR("SafeArrayAccessData failed with %x\n", hres
);
7106 SafeArrayDestroy(a
);
7109 for (j
= 0; j
< bound
.cElements
; j
++)
7110 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7111 hres
= SafeArrayUnaccessData(a
);
7114 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7115 SafeArrayDestroy(a
);
7118 V_ARRAY(&rgvarg
[i
]) = a
;
7119 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7121 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7123 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7124 if (wParamFlags
& PARAMFLAG_FIN
)
7125 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7127 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7128 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7129 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7131 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7133 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7134 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7138 /* FIXME: this doesn't work for VT_BYREF arguments if
7139 * they are not the same type as in the paramdesc */
7140 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7141 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7142 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7147 ERR("failed to convert param %d to %s from %s\n", i
,
7148 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7151 prgpvarg
[i
] = &rgvarg
[i
];
7155 prgpvarg
[i
] = src_arg
;
7158 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7159 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7160 && V_UNKNOWN(prgpvarg
[i
])) {
7161 IUnknown
*userdefined_iface
;
7164 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7168 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7170 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7174 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7175 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7178 else if (wParamFlags
& PARAMFLAG_FOPT
)
7181 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7182 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7184 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7190 VARIANTARG
*missing_arg
;
7191 /* if the function wants a pointer to a variant then
7192 * set that up, otherwise just pass the VT_ERROR in
7193 * the argument by value */
7194 if (rgvt
[i
] & VT_BYREF
)
7196 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7197 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7198 V_VARIANTREF(arg
) = missing_arg
;
7202 V_VT(missing_arg
) = VT_ERROR
;
7203 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7208 hres
= DISP_E_BADPARAMCOUNT
;
7212 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7214 /* VT_VOID is a special case for return types, so it is not
7215 * handled in the general function */
7216 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7217 V_VT(&varresult
) = VT_EMPTY
;
7220 V_VT(&varresult
) = 0;
7221 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7222 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7225 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7226 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7227 prgpvarg
, &varresult
);
7229 vargs_converted
= 0;
7231 for (i
= 0; i
< func_desc
->cParams
; i
++)
7233 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7234 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7236 if (wParamFlags
& PARAMFLAG_FLCID
)
7238 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7240 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7244 VariantInit(pVarResult
);
7245 /* deref return value */
7246 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7249 VARIANT_ClearInd(prgpvarg
[i
]);
7251 else if (vargs_converted
< pDispParams
->cArgs
)
7253 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7254 if (wParamFlags
& PARAMFLAG_FOUT
)
7256 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7258 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7262 ERR("failed to convert param %d to vt %d\n", i
,
7263 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7268 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7269 func_desc
->cParamsOpt
< 0 &&
7270 i
== func_desc
->cParams
-1)
7272 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7275 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7278 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7281 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7284 ERR("SafeArrayAccessData failed with %x\n", hres
);
7287 for (j
= 0; j
<= ubound
; j
++)
7288 VariantClear(&v
[j
]);
7289 hres
= SafeArrayUnaccessData(a
);
7292 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7296 VariantClear(&rgvarg
[i
]);
7299 else if (wParamFlags
& PARAMFLAG_FOPT
)
7301 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7302 VariantClear(&rgvarg
[i
]);
7305 VariantClear(&missing_arg
[i
]);
7308 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7310 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7311 hres
= DISP_E_EXCEPTION
;
7314 IErrorInfo
*pErrorInfo
;
7315 pExcepInfo
->scode
= V_ERROR(&varresult
);
7316 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7318 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7319 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7320 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7321 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7323 IErrorInfo_Release(pErrorInfo
);
7327 if (V_VT(&varresult
) != VT_ERROR
)
7329 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7333 VariantClear(pVarResult
);
7334 *pVarResult
= varresult
;
7337 VariantClear(&varresult
);
7340 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7341 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7342 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7343 (pDispParams
->cArgs
!= 0))
7345 if (V_VT(pVarResult
) == VT_DISPATCH
)
7347 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7348 /* Note: not VariantClear; we still need the dispatch
7349 * pointer to be valid */
7350 VariantInit(pVarResult
);
7351 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7352 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7353 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7354 IDispatch_Release(pDispatch
);
7358 VariantClear(pVarResult
);
7359 hres
= DISP_E_NOTACOLLECTION
;
7367 case FUNC_DISPATCH
: {
7370 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7371 if (SUCCEEDED(hres
)) {
7372 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7373 hres
= IDispatch_Invoke(
7374 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7375 pVarResult
,pExcepInfo
,pArgErr
7378 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7379 IDispatch_Release(disp
);
7381 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7385 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7390 TRACE("-- 0x%08x\n", hres
);
7393 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7396 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7397 if(FAILED(hres
)) return hres
;
7399 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7400 dump_VARDESC(var_desc
);
7401 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7405 /* not found, look for it in inherited interfaces */
7406 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7407 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7408 if(This
->impltypes
) {
7409 /* recursive search */
7411 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7412 if(SUCCEEDED(hres
)){
7413 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7414 ITypeInfo_Release(pTInfo
);
7417 WARN("Could not search inherited interface!\n");
7420 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7421 return DISP_E_MEMBERNOTFOUND
;
7424 /* ITypeInfo::GetDocumentation
7426 * Retrieves the documentation string, the complete Help file name and path,
7427 * and the context ID for the Help topic for a specified type description.
7429 * (Can be tested by the Visual Basic Editor in Word for instance.)
7431 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7432 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7433 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7435 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7436 const TLBFuncDesc
*pFDesc
;
7437 const TLBVarDesc
*pVDesc
;
7438 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7439 " HelpContext(%p) HelpFile(%p)\n",
7440 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7441 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7443 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7445 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7447 *pdwHelpContext
=This
->dwHelpContext
;
7449 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7451 }else {/* for a member */
7452 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7455 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7457 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7459 *pdwHelpContext
=pFDesc
->helpcontext
;
7461 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7464 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7467 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7469 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7471 *pdwHelpContext
=pVDesc
->HelpContext
;
7473 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7478 if(This
->impltypes
&&
7479 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
7480 /* recursive search */
7483 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7484 if(SUCCEEDED(result
)) {
7485 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7486 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7487 ITypeInfo_Release(pTInfo
);
7490 WARN("Could not search inherited interface!\n");
7493 WARN("member %d not found\n", memid
);
7494 return TYPE_E_ELEMENTNOTFOUND
;
7497 /* ITypeInfo::GetDllEntry
7499 * Retrieves a description or specification of an entry point for a function
7502 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7503 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7506 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7507 const TLBFuncDesc
*pFDesc
;
7509 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7511 if (pBstrDllName
) *pBstrDllName
= NULL
;
7512 if (pBstrName
) *pBstrName
= NULL
;
7513 if (pwOrdinal
) *pwOrdinal
= 0;
7515 if (This
->typekind
!= TKIND_MODULE
)
7516 return TYPE_E_BADMODULEKIND
;
7518 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7520 dump_TypeInfo(This
);
7522 dump_TLBFuncDescOne(pFDesc
);
7525 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7527 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7529 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7537 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7540 return TYPE_E_ELEMENTNOTFOUND
;
7543 /* internal function to make the inherited interfaces' methods appear
7544 * part of the interface */
7545 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7546 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7548 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7551 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7553 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7555 ITypeInfo
*pSubTypeInfo
;
7557 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7561 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7563 ITypeInfo_Release(pSubTypeInfo
);
7567 *hRefType
-= DISPATCH_HREF_OFFSET
;
7569 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7570 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7575 /* ITypeInfo::GetRefTypeInfo
7577 * If a type description references other type descriptions, it retrieves
7578 * the referenced type descriptions.
7580 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7583 ITypeInfo
**ppTInfo
)
7585 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7586 HRESULT result
= E_FAIL
;
7589 return E_INVALIDARG
;
7591 if ((INT
)hRefType
< 0) {
7592 ITypeInfoImpl
*pTypeInfoImpl
;
7594 if (!(This
->wTypeFlags
& TYPEFLAG_FDUAL
) ||
7595 !(This
->typekind
== TKIND_INTERFACE
||
7596 This
->typekind
== TKIND_DISPATCH
))
7597 return TYPE_E_ELEMENTNOTFOUND
;
7599 /* when we meet a DUAL typeinfo, we must create the alternate
7602 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7604 *pTypeInfoImpl
= *This
;
7605 pTypeInfoImpl
->ref
= 0;
7606 list_init(&pTypeInfoImpl
->custdata_list
);
7608 if (This
->typekind
== TKIND_INTERFACE
)
7609 pTypeInfoImpl
->typekind
= TKIND_DISPATCH
;
7611 pTypeInfoImpl
->typekind
= TKIND_INTERFACE
;
7613 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7614 /* the AddRef implicitly adds a reference to the parent typelib, which
7615 * stops the copied data from being destroyed until the new typeinfo's
7616 * refcount goes to zero, but we need to signal to the new instance to
7617 * not free its data structures when it is destroyed */
7618 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7620 ITypeInfo_AddRef(*ppTInfo
);
7623 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7624 (This
->typekind
== TKIND_DISPATCH
))
7626 HREFTYPE href_dispatch
= hRefType
;
7627 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7629 TLBRefType
*ref_type
;
7630 ITypeLib
*pTLib
= NULL
;
7633 if(!(hRefType
& 0x1)){
7634 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7636 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7639 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7640 ITypeInfo_AddRef(*ppTInfo
);
7646 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7648 if(ref_type
->reference
== (hRefType
& (~0x3)))
7651 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7653 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7657 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7659 TRACE("internal reference\n");
7660 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7662 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7663 TRACE("typeinfo in imported typelib that is already loaded\n");
7664 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7665 ITypeLib_AddRef(pTLib
);
7670 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7672 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7673 ref_type
->pImpTLInfo
->wVersionMajor
,
7674 ref_type
->pImpTLInfo
->wVersionMinor
,
7675 This
->pTypeLib
->syskind
,
7676 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7678 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7680 result
= LoadTypeLib(libnam
, &pTLib
);
7681 SysFreeString(libnam
);
7683 if(SUCCEEDED(result
)) {
7684 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7685 ITypeLib_AddRef(pTLib
);
7689 if(SUCCEEDED(result
)) {
7690 if(ref_type
->index
== TLB_REF_USE_GUID
)
7691 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7693 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7696 ITypeLib_Release(pTLib
);
7700 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7701 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7705 /* ITypeInfo::AddressOfMember
7707 * Retrieves the addresses of static functions or variables, such as those
7710 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7711 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7713 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7719 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7721 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7725 module
= LoadLibraryW(dll
);
7728 ERR("couldn't load %s\n", debugstr_w(dll
));
7730 SysFreeString(entry
);
7731 return STG_E_FILENOTFOUND
;
7733 /* FIXME: store library somewhere where we can free it */
7738 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7739 entryA
= heap_alloc(len
);
7740 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7742 *ppv
= GetProcAddress(module
, entryA
);
7744 ERR("function not found %s\n", debugstr_a(entryA
));
7750 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7752 ERR("function not found %d\n", ordinal
);
7756 SysFreeString(entry
);
7759 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7764 /* ITypeInfo::CreateInstance
7766 * Creates a new instance of a type that describes a component object class
7769 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7770 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7772 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7776 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7782 WARN("Not able to aggregate\n");
7783 return CLASS_E_NOAGGREGATION
;
7786 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7787 if(FAILED(hr
)) return hr
;
7789 if(pTA
->typekind
!= TKIND_COCLASS
)
7791 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7797 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7800 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7801 TRACE("GetActiveObject rets %08x\n", hr
);
7804 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7805 IUnknown_Release(pUnk
);
7810 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7811 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7815 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7819 /* ITypeInfo::GetMops
7821 * Retrieves marshalling information.
7823 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7826 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7827 FIXME("(%p %d) stub!\n", This
, memid
);
7832 /* ITypeInfo::GetContainingTypeLib
7834 * Retrieves the containing type library and the index of the type description
7835 * within that type library.
7837 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7838 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7840 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7842 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7844 *pIndex
=This
->index
;
7845 TRACE("returning pIndex=%d\n", *pIndex
);
7849 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7850 ITypeLib_AddRef(*ppTLib
);
7851 TRACE("returning ppTLib=%p\n", *ppTLib
);
7857 /* ITypeInfo::ReleaseTypeAttr
7859 * Releases a TYPEATTR previously returned by Get
7862 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7863 TYPEATTR
* pTypeAttr
)
7865 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7866 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7867 heap_free(pTypeAttr
);
7870 /* ITypeInfo::ReleaseFuncDesc
7872 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7874 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7876 FUNCDESC
*pFuncDesc
)
7878 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7881 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7883 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7884 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7885 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7887 SysFreeString((BSTR
)pFuncDesc
);
7890 /* ITypeInfo::ReleaseVarDesc
7892 * Releases a VARDESC previously returned by GetVarDesc.
7894 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7897 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7898 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7900 TLB_FreeVarDesc(pVarDesc
);
7903 /* ITypeInfo2::GetTypeKind
7905 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7908 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7909 TYPEKIND
*pTypeKind
)
7911 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7912 *pTypeKind
=This
->typekind
;
7913 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7917 /* ITypeInfo2::GetTypeFlags
7919 * Returns the type flags without any allocations. This returns a DWORD type
7920 * flag, which expands the type flags without growing the TYPEATTR (type
7924 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7926 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7927 *pTypeFlags
=This
->wTypeFlags
;
7928 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7932 /* ITypeInfo2::GetFuncIndexOfMemId
7933 * Binds to a specific member based on a known DISPID, where the member name
7934 * is not known (for example, when binding to a default member).
7937 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7938 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7940 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7944 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
7945 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7946 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7949 if(fdc
< This
->cFuncs
) {
7953 result
= TYPE_E_ELEMENTNOTFOUND
;
7955 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7956 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7960 /* TypeInfo2::GetVarIndexOfMemId
7962 * Binds to a specific member based on a known DISPID, where the member name
7963 * is not known (for example, when binding to a default member).
7966 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7967 MEMBERID memid
, UINT
*pVarIndex
)
7969 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7970 TLBVarDesc
*pVarInfo
;
7972 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7974 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7976 return TYPE_E_ELEMENTNOTFOUND
;
7978 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7983 /* ITypeInfo2::GetCustData
7985 * Gets the custom data
7987 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7992 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7993 TLBCustData
*pCData
;
7995 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7997 if(!guid
|| !pVarVal
)
7998 return E_INVALIDARG
;
8000 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8002 VariantInit( pVarVal
);
8004 VariantCopy( pVarVal
, &pCData
->data
);
8006 VariantClear( pVarVal
);
8010 /* ITypeInfo2::GetFuncCustData
8012 * Gets the custom data
8014 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8020 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8021 TLBCustData
*pCData
;
8022 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8024 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8026 if(index
>= This
->cFuncs
)
8027 return TYPE_E_ELEMENTNOTFOUND
;
8029 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8031 return TYPE_E_ELEMENTNOTFOUND
;
8033 VariantInit(pVarVal
);
8034 VariantCopy(pVarVal
, &pCData
->data
);
8039 /* ITypeInfo2::GetParamCustData
8041 * Gets the custom data
8043 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8050 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8051 TLBCustData
*pCData
;
8052 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8054 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8055 debugstr_guid(guid
), pVarVal
);
8057 if(indexFunc
>= This
->cFuncs
)
8058 return TYPE_E_ELEMENTNOTFOUND
;
8060 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8061 return TYPE_E_ELEMENTNOTFOUND
;
8063 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8065 return TYPE_E_ELEMENTNOTFOUND
;
8067 VariantInit(pVarVal
);
8068 VariantCopy(pVarVal
, &pCData
->data
);
8073 /* ITypeInfo2::GetVarCustData
8075 * Gets the custom data
8077 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8083 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8084 TLBCustData
*pCData
;
8085 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8087 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8089 if(index
>= This
->cVars
)
8090 return TYPE_E_ELEMENTNOTFOUND
;
8092 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8094 return TYPE_E_ELEMENTNOTFOUND
;
8096 VariantInit(pVarVal
);
8097 VariantCopy(pVarVal
, &pCData
->data
);
8102 /* ITypeInfo2::GetImplCustData
8104 * Gets the custom data
8106 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8112 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8113 TLBCustData
*pCData
;
8114 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8116 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8118 if(index
>= This
->cImplTypes
)
8119 return TYPE_E_ELEMENTNOTFOUND
;
8121 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8123 return TYPE_E_ELEMENTNOTFOUND
;
8125 VariantInit(pVarVal
);
8126 VariantCopy(pVarVal
, &pCData
->data
);
8131 /* ITypeInfo2::GetDocumentation2
8133 * Retrieves the documentation string, the complete Help file name and path,
8134 * the localization context to use, and the context ID for the library Help
8135 * topic in the Help file.
8138 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8142 BSTR
*pbstrHelpString
,
8143 DWORD
*pdwHelpStringContext
,
8144 BSTR
*pbstrHelpStringDll
)
8146 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8147 const TLBFuncDesc
*pFDesc
;
8148 const TLBVarDesc
*pVDesc
;
8149 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8150 "HelpStringContext(%p) HelpStringDll(%p)\n",
8151 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8152 pbstrHelpStringDll
);
8153 /* the help string should be obtained from the helpstringdll,
8154 * using the _DLLGetDocumentation function, based on the supplied
8155 * lcid. Nice to do sometime...
8157 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8159 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8160 if(pdwHelpStringContext
)
8161 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8162 if(pbstrHelpStringDll
)
8163 *pbstrHelpStringDll
=
8164 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8166 }else {/* for a member */
8167 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
8170 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8171 if(pdwHelpStringContext
)
8172 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8173 if(pbstrHelpStringDll
)
8174 *pbstrHelpStringDll
=
8175 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8178 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8181 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8182 if(pdwHelpStringContext
)
8183 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8184 if(pbstrHelpStringDll
)
8185 *pbstrHelpStringDll
=
8186 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8190 return TYPE_E_ELEMENTNOTFOUND
;
8193 /* ITypeInfo2::GetAllCustData
8195 * Gets all custom data items for the Type info.
8198 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8200 CUSTDATA
*pCustData
)
8202 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8204 TRACE("%p %p\n", This
, pCustData
);
8206 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8209 /* ITypeInfo2::GetAllFuncCustData
8211 * Gets all custom data items for the specified Function
8214 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8217 CUSTDATA
*pCustData
)
8219 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8220 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8222 TRACE("%p %u %p\n", This
, index
, pCustData
);
8224 if(index
>= This
->cFuncs
)
8225 return TYPE_E_ELEMENTNOTFOUND
;
8227 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8230 /* ITypeInfo2::GetAllParamCustData
8232 * Gets all custom data items for the Functions
8235 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8236 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8238 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8239 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8241 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8243 if(indexFunc
>= This
->cFuncs
)
8244 return TYPE_E_ELEMENTNOTFOUND
;
8246 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8247 return TYPE_E_ELEMENTNOTFOUND
;
8249 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8252 /* ITypeInfo2::GetAllVarCustData
8254 * Gets all custom data items for the specified Variable
8257 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8258 UINT index
, CUSTDATA
*pCustData
)
8260 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8261 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8263 TRACE("%p %u %p\n", This
, index
, pCustData
);
8265 if(index
>= This
->cVars
)
8266 return TYPE_E_ELEMENTNOTFOUND
;
8268 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8271 /* ITypeInfo2::GetAllImplCustData
8273 * Gets all custom data items for the specified implementation type
8276 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8279 CUSTDATA
*pCustData
)
8281 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8282 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8284 TRACE("%p %u %p\n", This
, index
, pCustData
);
8286 if(index
>= This
->cImplTypes
)
8287 return TYPE_E_ELEMENTNOTFOUND
;
8289 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8292 static const ITypeInfo2Vtbl tinfvt
=
8295 ITypeInfo_fnQueryInterface
,
8297 ITypeInfo_fnRelease
,
8299 ITypeInfo_fnGetTypeAttr
,
8300 ITypeInfo_fnGetTypeComp
,
8301 ITypeInfo_fnGetFuncDesc
,
8302 ITypeInfo_fnGetVarDesc
,
8303 ITypeInfo_fnGetNames
,
8304 ITypeInfo_fnGetRefTypeOfImplType
,
8305 ITypeInfo_fnGetImplTypeFlags
,
8306 ITypeInfo_fnGetIDsOfNames
,
8308 ITypeInfo_fnGetDocumentation
,
8309 ITypeInfo_fnGetDllEntry
,
8310 ITypeInfo_fnGetRefTypeInfo
,
8311 ITypeInfo_fnAddressOfMember
,
8312 ITypeInfo_fnCreateInstance
,
8313 ITypeInfo_fnGetMops
,
8314 ITypeInfo_fnGetContainingTypeLib
,
8315 ITypeInfo_fnReleaseTypeAttr
,
8316 ITypeInfo_fnReleaseFuncDesc
,
8317 ITypeInfo_fnReleaseVarDesc
,
8319 ITypeInfo2_fnGetTypeKind
,
8320 ITypeInfo2_fnGetTypeFlags
,
8321 ITypeInfo2_fnGetFuncIndexOfMemId
,
8322 ITypeInfo2_fnGetVarIndexOfMemId
,
8323 ITypeInfo2_fnGetCustData
,
8324 ITypeInfo2_fnGetFuncCustData
,
8325 ITypeInfo2_fnGetParamCustData
,
8326 ITypeInfo2_fnGetVarCustData
,
8327 ITypeInfo2_fnGetImplTypeCustData
,
8328 ITypeInfo2_fnGetDocumentation2
,
8329 ITypeInfo2_fnGetAllCustData
,
8330 ITypeInfo2_fnGetAllFuncCustData
,
8331 ITypeInfo2_fnGetAllParamCustData
,
8332 ITypeInfo2_fnGetAllVarCustData
,
8333 ITypeInfo2_fnGetAllImplTypeCustData
,
8336 /******************************************************************************
8337 * CreateDispTypeInfo [OLEAUT32.31]
8339 * Build type information for an object so it can be called through an
8340 * IDispatch interface.
8343 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8344 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8347 * This call allows an objects methods to be accessed through IDispatch, by
8348 * building an ITypeInfo object that IDispatch can use to call through.
8350 HRESULT WINAPI
CreateDispTypeInfo(
8351 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8352 LCID lcid
, /* [I] Locale Id */
8353 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8355 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8356 ITypeLibImpl
*pTypeLibImpl
;
8357 unsigned int param
, func
;
8358 TLBFuncDesc
*pFuncDesc
;
8362 pTypeLibImpl
= TypeLibImpl_Constructor();
8363 if (!pTypeLibImpl
) return E_FAIL
;
8365 pTypeLibImpl
->TypeInfoCount
= 2;
8366 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8368 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8369 pTIIface
->pTypeLib
= pTypeLibImpl
;
8370 pTIIface
->index
= 0;
8371 pTIIface
->Name
= NULL
;
8372 pTIIface
->dwHelpContext
= -1;
8373 pTIIface
->guid
= NULL
;
8374 pTIIface
->lcid
= lcid
;
8375 pTIIface
->typekind
= TKIND_INTERFACE
;
8376 pTIIface
->wMajorVerNum
= 0;
8377 pTIIface
->wMinorVerNum
= 0;
8378 pTIIface
->cbAlignment
= 2;
8379 pTIIface
->cbSizeInstance
= -1;
8380 pTIIface
->cbSizeVft
= -1;
8381 pTIIface
->cFuncs
= 0;
8382 pTIIface
->cImplTypes
= 0;
8383 pTIIface
->cVars
= 0;
8384 pTIIface
->wTypeFlags
= 0;
8385 pTIIface
->hreftype
= 0;
8387 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8388 pFuncDesc
= pTIIface
->funcdescs
;
8389 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8390 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8391 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8392 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8393 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8394 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8395 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8396 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8397 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8398 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8399 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8400 pFuncDesc
->funcdesc
.cScodes
= 0;
8401 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8402 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8403 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8404 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8405 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8406 md
->cArgs
* sizeof(ELEMDESC
));
8407 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8408 for(param
= 0; param
< md
->cArgs
; param
++) {
8409 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8410 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8412 pFuncDesc
->helpcontext
= 0;
8413 pFuncDesc
->HelpStringContext
= 0;
8414 pFuncDesc
->HelpString
= NULL
;
8415 pFuncDesc
->Entry
= NULL
;
8416 list_init(&pFuncDesc
->custdata_list
);
8421 dump_TypeInfo(pTIIface
);
8423 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8424 pTIClass
->pTypeLib
= pTypeLibImpl
;
8425 pTIClass
->index
= 1;
8426 pTIClass
->Name
= NULL
;
8427 pTIClass
->dwHelpContext
= -1;
8428 pTIClass
->guid
= NULL
;
8429 pTIClass
->lcid
= lcid
;
8430 pTIClass
->typekind
= TKIND_COCLASS
;
8431 pTIClass
->wMajorVerNum
= 0;
8432 pTIClass
->wMinorVerNum
= 0;
8433 pTIClass
->cbAlignment
= 2;
8434 pTIClass
->cbSizeInstance
= -1;
8435 pTIClass
->cbSizeVft
= -1;
8436 pTIClass
->cFuncs
= 0;
8437 pTIClass
->cImplTypes
= 1;
8438 pTIClass
->cVars
= 0;
8439 pTIClass
->wTypeFlags
= 0;
8440 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8442 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8444 ref
= heap_alloc_zero(sizeof(*ref
));
8445 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8446 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8448 dump_TypeInfo(pTIClass
);
8450 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8452 ITypeInfo_AddRef(*pptinfo
);
8453 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8459 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8461 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8463 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8466 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8468 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8470 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8473 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8475 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8477 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8480 static HRESULT WINAPI
ITypeComp_fnBind(
8485 ITypeInfo
** ppTInfo
,
8486 DESCKIND
* pDescKind
,
8489 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8490 const TLBFuncDesc
*pFDesc
;
8491 const TLBVarDesc
*pVDesc
;
8492 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8495 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8497 *pDescKind
= DESCKIND_NONE
;
8498 pBindPtr
->lpfuncdesc
= NULL
;
8501 for(fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8502 pFDesc
= &This
->funcdescs
[fdc
];
8503 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8504 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8507 /* name found, but wrong flags */
8508 hr
= TYPE_E_TYPEMISMATCH
;
8512 if (fdc
< This
->cFuncs
)
8514 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8516 &pBindPtr
->lpfuncdesc
,
8517 This
->typekind
== TKIND_DISPATCH
);
8520 *pDescKind
= DESCKIND_FUNCDESC
;
8521 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8522 ITypeInfo_AddRef(*ppTInfo
);
8525 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, szName
);
8527 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8530 *pDescKind
= DESCKIND_VARDESC
;
8531 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8532 ITypeInfo_AddRef(*ppTInfo
);
8537 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8538 /* recursive search */
8542 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8545 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8546 ITypeInfo_Release(pTInfo
);
8550 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8551 ITypeComp_Release(pTComp
);
8552 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8553 This
->typekind
== TKIND_DISPATCH
)
8555 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8556 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8557 SysFreeString((BSTR
)tmp
);
8561 WARN("Could not search inherited interface!\n");
8563 if (hr
== DISP_E_MEMBERNOTFOUND
)
8565 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8569 static HRESULT WINAPI
ITypeComp_fnBindType(
8573 ITypeInfo
** ppTInfo
,
8574 ITypeComp
** ppTComp
)
8576 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8578 /* strange behaviour (does nothing) but like the
8581 if (!ppTInfo
|| !ppTComp
)
8590 static const ITypeCompVtbl tcompvt
=
8593 ITypeComp_fnQueryInterface
,
8595 ITypeComp_fnRelease
,
8598 ITypeComp_fnBindType
8601 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8602 ICreateTypeLib2
** ppctlib
)
8607 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8609 if (!szFile
) return E_INVALIDARG
;
8611 This
= TypeLibImpl_Constructor();
8613 return E_OUTOFMEMORY
;
8615 This
->lcid
= GetSystemDefaultLCID();
8616 This
->syskind
= syskind
;
8617 This
->ptr_size
= get_ptr_size(syskind
);
8619 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8621 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8622 return E_OUTOFMEMORY
;
8624 lstrcpyW(This
->path
, szFile
);
8626 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8627 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8631 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8632 REFIID riid
, void **object
)
8634 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8636 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8639 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8641 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8643 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8646 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8648 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8650 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8653 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8654 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8656 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8657 ITypeInfoImpl
*info
;
8660 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8662 if (!ctinfo
|| !name
)
8663 return E_INVALIDARG
;
8665 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8667 return TYPE_E_NAMECONFLICT
;
8669 if (This
->typeinfos
)
8670 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8671 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8673 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8675 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8677 info
->pTypeLib
= This
;
8678 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8679 info
->index
= This
->TypeInfoCount
;
8680 info
->typekind
= kind
;
8681 info
->cbAlignment
= 4;
8683 switch(info
->typekind
) {
8685 case TKIND_INTERFACE
:
8686 case TKIND_DISPATCH
:
8688 info
->cbSizeInstance
= This
->ptr_size
;
8692 info
->cbSizeInstance
= 0;
8695 info
->cbSizeInstance
= 2;
8698 info
->cbSizeInstance
= -0x75;
8701 FIXME("unrecognized typekind %d\n", info
->typekind
);
8702 info
->cbSizeInstance
= 0xdeadbeef;
8706 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8707 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8709 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8713 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8715 ++This
->TypeInfoCount
;
8720 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8723 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8725 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8728 return E_INVALIDARG
;
8730 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8735 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8736 WORD majorVerNum
, WORD minorVerNum
)
8738 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8740 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8742 This
->ver_major
= majorVerNum
;
8743 This
->ver_minor
= minorVerNum
;
8748 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8751 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8753 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8755 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8760 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8763 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8765 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8768 return E_INVALIDARG
;
8770 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8775 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8776 LPOLESTR helpFileName
)
8778 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8780 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8783 return E_INVALIDARG
;
8785 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8790 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8793 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8795 TRACE("%p %d\n", This
, helpContext
);
8797 This
->dwHelpContext
= helpContext
;
8802 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8805 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8807 TRACE("%p %x\n", This
, lcid
);
8809 This
->set_lcid
= lcid
;
8814 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8817 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8819 TRACE("%p %x\n", This
, libFlags
);
8821 This
->libflags
= libFlags
;
8826 typedef struct tagWMSFT_SegContents
{
8829 } WMSFT_SegContents
;
8831 typedef struct tagWMSFT_TLBFile
{
8833 WMSFT_SegContents typeinfo_seg
;
8834 WMSFT_SegContents impfile_seg
;
8835 WMSFT_SegContents impinfo_seg
;
8836 WMSFT_SegContents ref_seg
;
8837 WMSFT_SegContents guidhash_seg
;
8838 WMSFT_SegContents guid_seg
;
8839 WMSFT_SegContents namehash_seg
;
8840 WMSFT_SegContents name_seg
;
8841 WMSFT_SegContents string_seg
;
8842 WMSFT_SegContents typdesc_seg
;
8843 WMSFT_SegContents arraydesc_seg
;
8844 WMSFT_SegContents custdata_seg
;
8845 WMSFT_SegContents cdguids_seg
;
8847 WMSFT_SegContents aux_seg
;
8850 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8851 WMSFT_TLBFile
*file
)
8857 file
->string_seg
.len
= 0;
8858 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8861 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8863 return E_UNEXPECTED
;
8865 size
+= sizeof(INT16
);
8867 size
= (size
+ 4) & ~0x3;
8871 file
->string_seg
.len
+= size
;
8873 /* temporarily use str->offset to store the length of the aligned,
8874 * converted string */
8878 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8881 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8884 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8885 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8887 heap_free(file
->string_seg
.data
);
8888 return E_UNEXPECTED
;
8891 *((INT16
*)data
) = size
;
8893 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8897 str
->offset
= last_offs
;
8904 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8905 WMSFT_TLBFile
*file
)
8910 MSFT_NameIntro
*last_intro
= NULL
;
8912 file
->header
.nametablecount
= 0;
8913 file
->header
.nametablechars
= 0;
8915 file
->name_seg
.len
= 0;
8916 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8919 size
= strlenW(str
->str
);
8920 file
->header
.nametablechars
+= size
;
8921 file
->header
.nametablecount
++;
8923 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8925 return E_UNEXPECTED
;
8927 size
+= sizeof(MSFT_NameIntro
);
8929 size
= (size
+ 4) & ~0x3;
8933 file
->name_seg
.len
+= size
;
8935 /* temporarily use str->offset to store the length of the aligned,
8936 * converted string */
8940 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8941 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
8944 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8946 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8948 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8949 data
+ sizeof(MSFT_NameIntro
),
8950 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8952 heap_free(file
->name_seg
.data
);
8953 return E_UNEXPECTED
;
8955 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
8957 intro
->hreftype
= -1; /* TODO? */
8958 intro
->namelen
= size
& 0xFF;
8959 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8960 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
8961 intro
->namelen
|= hash
<< 16;
8962 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
8963 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
8965 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
8966 str
->offset
- size
- sizeof(MSFT_NameIntro
));
8968 /* update str->offset to actual value to use in other
8969 * compilation functions that require positions within
8970 * the string table */
8974 str
->offset
= last_offs
;
8979 last_intro
->hreftype
= 0; /* last one is 0? */
8984 static inline int hash_guid(GUID
*guid
)
8988 for (i
= 0; i
< 8; i
++)
8989 hash
^= ((const short *)guid
)[i
];
8994 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
8997 MSFT_GuidEntry
*entry
;
8999 int hash_key
, *guidhashtab
;
9001 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9002 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9004 entry
= file
->guid_seg
.data
;
9006 guidhashtab
= file
->guidhash_seg
.data
;
9007 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9008 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9009 entry
->hreftype
= guid
->hreftype
;
9011 hash_key
= hash_guid(&guid
->guid
);
9012 entry
->next_hash
= guidhashtab
[hash_key
];
9013 guidhashtab
[hash_key
] = offs
;
9015 guid
->offset
= offs
;
9016 offs
+= sizeof(MSFT_GuidEntry
);
9023 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9026 VARTYPE arg_type
= V_VT(value
);
9029 DWORD ret
= file
->custdata_seg
.len
;
9031 if(arg_type
== VT_INT
)
9033 if(arg_type
== VT_UINT
)
9037 if(V_VT(value
) != arg_type
) {
9038 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9040 ERR("VariantChangeType failed: %08x\n", hres
);
9045 /* Check if default value can be stored in-place */
9050 if(V_UI4(&v
) > 0x3ffffff)
9063 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9066 /* have to allocate space in custdata_seg */
9075 /* Construct the data to be allocated */
9078 if(file
->custdata_seg
.data
){
9079 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9080 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9081 file
->custdata_seg
.len
+= sizeof(int) * 2;
9083 file
->custdata_seg
.len
= sizeof(int) * 2;
9084 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9087 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9088 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9090 /* TODO: Check if the encoded data is already present in custdata_seg */
9096 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9099 if(file
->custdata_seg
.data
){
9100 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9101 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9102 file
->custdata_seg
.len
+= len
;
9104 file
->custdata_seg
.len
= len
;
9105 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9108 *((unsigned short *)data
) = V_VT(value
);
9109 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9110 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9111 if(V_BSTR(&v
)[i
] <= 0x7f)
9112 data
[i
+6] = V_BSTR(&v
)[i
];
9116 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9117 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9120 /* TODO: Check if the encoded data is already present in custdata_seg */
9125 FIXME("Argument type not yet handled\n");
9130 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9132 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9134 DWORD offs
= file
->arraydesc_seg
.len
;
9138 /* TODO: we should check for duplicates, but that's harder because each
9139 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9140 * at the library-level) */
9142 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9143 if(!file
->arraydesc_seg
.data
)
9144 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9146 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9147 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9149 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9150 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9151 for(i
= 0; i
< desc
->cDims
; ++i
){
9152 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9153 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9159 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9165 VARTYPE vt
, subtype
;
9176 vt
= desc
->vt
& VT_TYPEMASK
;
9178 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9180 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9181 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9183 *out_size
+= 2 * sizeof(DWORD
);
9184 }else if(vt
== VT_CARRAY
){
9185 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9186 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9188 }else if(vt
== VT_USERDEFINED
){
9189 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9190 encoded
[1] = desc
->u
.hreftype
;
9191 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9193 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9211 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9214 data
= file
->typdesc_seg
.data
;
9215 while(offs
< file
->typdesc_seg
.len
){
9216 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9218 offs
+= sizeof(encoded
);
9221 file
->typdesc_seg
.len
+= sizeof(encoded
);
9222 if(!file
->typdesc_seg
.data
)
9223 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9225 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9227 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9232 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9234 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9235 DWORD ret
= cdguids_seg
->len
, offs
;
9236 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
9239 if(list_empty(custdata_list
))
9242 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9243 if(!cdguids_seg
->data
){
9244 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9246 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9248 offs
= ret
+ sizeof(MSFT_CDGuid
);
9249 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9250 cdguid
->GuidOffset
= cd
->guid
->offset
;
9251 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9252 cdguid
->next
= offs
;
9253 offs
+= sizeof(MSFT_CDGuid
);
9263 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9264 WMSFT_TLBFile
*file
)
9266 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9267 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9268 MSFT_VarRecord
*varrecord
;
9269 MSFT_FuncRecord
*funcrecord
;
9271 DWORD
*name
, *offsets
, offs
;
9273 for(i
= 0; i
< info
->cFuncs
; ++i
){
9274 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9276 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9278 /* optional fields */
9279 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9280 if(!list_empty(&desc
->custdata_list
))
9281 recorded_size
+= 7 * sizeof(INT
);
9282 else if(desc
->HelpStringContext
!= 0)
9283 recorded_size
+= 6 * sizeof(INT
);
9285 else if(desc
->Entry
)
9286 recorded_size
+= 3 * sizeof(INT
);
9287 else if(desc
->HelpString
)
9288 recorded_size
+= 2 * sizeof(INT
);
9289 else if(desc
->helpcontext
)
9290 recorded_size
+= sizeof(INT
);
9292 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9294 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9295 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9296 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9301 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9304 for(i
= 0; i
< info
->cVars
; ++i
){
9305 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9307 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9309 /* optional fields */
9310 if(desc
->HelpStringContext
!= 0)
9311 recorded_size
+= 5 * sizeof(INT
);
9312 else if(!list_empty(&desc
->custdata_list
))
9313 recorded_size
+= 4 * sizeof(INT
);
9315 else if(desc
->HelpString
)
9316 recorded_size
+= 2 * sizeof(INT
);
9317 else if(desc
->HelpContext
!= 0)
9318 recorded_size
+= sizeof(INT
);
9320 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9323 if(!recorded_size
&& !extra_size
)
9326 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9328 aux_seg
->len
+= recorded_size
+ extra_size
;
9330 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9333 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9335 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9337 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9339 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9342 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9343 for(i
= 0; i
< info
->cFuncs
; ++i
){
9344 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9345 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9347 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9348 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9349 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9350 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9353 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9358 * ^has_param_defaults
9359 * ^oEntry_is_intresource
9361 funcrecord
->FKCCIC
=
9362 desc
->funcdesc
.funckind
|
9363 (desc
->funcdesc
.invkind
<< 3) |
9364 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9365 (desc
->funcdesc
.callconv
<< 8);
9367 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9368 funcrecord
->FKCCIC
|= 0x2000;
9370 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9371 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9372 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9373 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9376 if(paramdefault_size
> 0)
9377 funcrecord
->FKCCIC
|= 0x1000;
9379 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9380 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9382 /* optional fields */
9384 if(!list_empty(&desc
->custdata_list
)){
9385 size
+= 7 * sizeof(INT
);
9386 funcrecord
->HelpContext
= desc
->helpcontext
;
9387 if(desc
->HelpString
)
9388 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9390 funcrecord
->oHelpString
= -1;
9392 funcrecord
->oEntry
= -1;
9393 else if(IS_INTRESOURCE(desc
->Entry
))
9394 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9396 funcrecord
->oEntry
= desc
->Entry
->offset
;
9397 funcrecord
->res9
= -1;
9398 funcrecord
->resA
= -1;
9399 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9400 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9401 }else if(desc
->HelpStringContext
!= 0){
9402 size
+= 6 * sizeof(INT
);
9403 funcrecord
->HelpContext
= desc
->helpcontext
;
9404 if(desc
->HelpString
)
9405 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9407 funcrecord
->oHelpString
= -1;
9409 funcrecord
->oEntry
= -1;
9410 else if(IS_INTRESOURCE(desc
->Entry
))
9411 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9413 funcrecord
->oEntry
= desc
->Entry
->offset
;
9414 funcrecord
->res9
= -1;
9415 funcrecord
->resA
= -1;
9416 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9417 }else if(desc
->Entry
){
9418 size
+= 3 * sizeof(INT
);
9419 funcrecord
->HelpContext
= desc
->helpcontext
;
9420 if(desc
->HelpString
)
9421 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9423 funcrecord
->oHelpString
= -1;
9425 funcrecord
->oEntry
= -1;
9426 else if(IS_INTRESOURCE(desc
->Entry
))
9427 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9429 funcrecord
->oEntry
= desc
->Entry
->offset
;
9430 }else if(desc
->HelpString
){
9431 size
+= 2 * sizeof(INT
);
9432 funcrecord
->HelpContext
= desc
->helpcontext
;
9433 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9434 }else if(desc
->helpcontext
){
9435 size
+= sizeof(INT
);
9436 funcrecord
->HelpContext
= desc
->helpcontext
;
9439 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9440 size
+= paramdefault_size
;
9442 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9443 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9445 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9446 if(desc
->pParamDesc
[j
].Name
)
9447 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9450 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9452 if(paramdefault_size
){
9453 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9454 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9455 else if(paramdefault_size
)
9460 size
+= sizeof(MSFT_ParameterInfo
);
9463 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9469 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9472 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9473 for(i
= 0; i
< info
->cVars
; ++i
){
9474 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9475 DWORD size
= 5 * sizeof(INT
);
9477 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9478 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9479 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9480 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9482 if(desc
->vardesc
.varkind
== VAR_CONST
){
9483 varrecord
->vardescsize
+= sizeof(VARIANT
);
9484 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9486 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9489 if(desc
->HelpStringContext
!= 0){
9490 size
+= 5 * sizeof(INT
);
9491 varrecord
->HelpContext
= desc
->HelpContext
;
9492 if(desc
->HelpString
)
9493 varrecord
->HelpString
= desc
->HelpString
->offset
;
9495 varrecord
->HelpString
= -1;
9496 varrecord
->res9
= -1;
9497 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9498 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9499 }else if(!list_empty(&desc
->custdata_list
)){
9500 size
+= 4 * sizeof(INT
);
9501 varrecord
->HelpContext
= desc
->HelpContext
;
9502 if(desc
->HelpString
)
9503 varrecord
->HelpString
= desc
->HelpString
->offset
;
9505 varrecord
->HelpString
= -1;
9506 varrecord
->res9
= -1;
9507 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9508 }else if(desc
->HelpString
){
9509 size
+= 2 * sizeof(INT
);
9510 varrecord
->HelpContext
= desc
->HelpContext
;
9511 if(desc
->HelpString
)
9512 varrecord
->HelpString
= desc
->HelpString
->offset
;
9514 varrecord
->HelpString
= -1;
9515 }else if(desc
->HelpContext
!= 0){
9516 size
+= sizeof(INT
);
9517 varrecord
->HelpContext
= desc
->HelpContext
;
9520 varrecord
->Info
= size
| (i
<< 16);
9526 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9529 memid
= (MEMBERID
*)varrecord
;
9530 for(i
= 0; i
< info
->cFuncs
; ++i
){
9531 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9532 *memid
= desc
->funcdesc
.memid
;
9535 for(i
= 0; i
< info
->cVars
; ++i
){
9536 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9537 *memid
= desc
->vardesc
.memid
;
9541 name
= (UINT
*)memid
;
9542 for(i
= 0; i
< info
->cFuncs
; ++i
){
9543 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9545 *name
= desc
->Name
->offset
;
9550 for(i
= 0; i
< info
->cVars
; ++i
){
9551 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9553 *name
= desc
->Name
->offset
;
9562 typedef struct tagWMSFT_RefChunk
{
9569 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9571 DWORD offs
= file
->ref_seg
.len
, i
;
9572 WMSFT_RefChunk
*chunk
;
9574 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9575 if(!file
->ref_seg
.data
)
9576 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9578 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9580 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9582 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9583 chunk
->href
= info
->impltypes
[i
].hRef
;
9584 chunk
->res04
= info
->impltypes
[i
].implflags
;
9586 if(i
< info
->cImplTypes
- 1)
9587 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9596 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9600 size
= sizeof(MSFT_TypeInfoBase
);
9603 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9604 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9605 base
->typekind
= TKIND_DISPATCH
;
9607 base
->typekind
= info
->typekind
;
9608 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9609 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9610 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9615 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9621 base
->posguid
= info
->guid
->offset
;
9624 base
->flags
= info
->wTypeFlags
;
9626 base
->NameOffset
= info
->Name
->offset
;
9628 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9629 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9631 base
->NameOffset
= -1;
9633 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9635 base
->docstringoffs
= info
->DocString
->offset
;
9637 base
->docstringoffs
= -1;
9638 base
->helpstringcontext
= info
->dwHelpStringContext
;
9639 base
->helpcontext
= info
->dwHelpContext
;
9640 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9641 base
->cImplTypes
= info
->cImplTypes
;
9642 base
->cbSizeVft
= info
->cbSizeVft
;
9643 base
->size
= info
->cbSizeInstance
;
9644 if(info
->typekind
== TKIND_COCLASS
){
9645 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9646 }else if(info
->typekind
== TKIND_ALIAS
){
9647 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9648 }else if(info
->typekind
== TKIND_MODULE
){
9650 base
->datatype1
= info
->DllName
->offset
;
9652 base
->datatype1
= -1;
9654 if(info
->cImplTypes
> 0)
9655 base
->datatype1
= info
->impltypes
[0].hRef
;
9657 base
->datatype1
= -1;
9659 base
->datatype2
= index
; /* FIXME: i think there's more here */
9667 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9671 file
->typeinfo_seg
.len
= 0;
9672 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9673 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9674 *junk
= file
->typeinfo_seg
.len
;
9676 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9679 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9680 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9682 file
->aux_seg
.len
= 0;
9683 file
->aux_seg
.data
= NULL
;
9685 file
->typeinfo_seg
.len
= 0;
9686 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9687 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9688 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9689 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9693 typedef struct tagWMSFT_ImpFile
{
9699 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9702 WMSFT_ImpFile
*impfile
;
9704 DWORD last_offs
= 0;
9706 file
->impfile_seg
.len
= 0;
9707 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9711 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9715 path
= implib
->name
;
9716 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9718 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9721 size
+= sizeof(INT16
);
9723 size
= (size
+ 4) & ~0x3;
9727 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9730 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9732 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9733 int strlen
= 0, size
;
9735 impfile
= (WMSFT_ImpFile
*)data
;
9736 impfile
->guid_offs
= implib
->guid
->offset
;
9737 impfile
->lcid
= implib
->lcid
;
9738 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9740 data
+= sizeof(WMSFT_ImpFile
);
9743 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9747 path
= implib
->name
;
9748 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9749 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9751 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9754 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9756 size
= strlen
+ sizeof(INT16
);
9758 size
= (size
+ 4) & ~0x3;
9761 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9764 implib
->offset
= last_offs
;
9765 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9769 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9772 TLBRefType
*ref_type
;
9775 WMSFT_compile_impfile(This
, file
);
9777 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9778 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9780 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9781 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9782 if(ref_type
->index
== TLB_REF_USE_GUID
){
9783 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9784 info
->oGuid
= ref_type
->guid
->offset
;
9786 info
->oGuid
= ref_type
->index
;
9787 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9793 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9795 file
->guidhash_seg
.len
= 0x80;
9796 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9797 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9800 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9802 file
->namehash_seg
.len
= 0x200;
9803 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9804 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9807 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9809 if(contents
&& contents
->len
){
9810 segdir
->offset
= *running_offset
;
9811 segdir
->length
= contents
->len
;
9812 *running_offset
+= segdir
->length
;
9814 segdir
->offset
= -1;
9818 /* TODO: do these ever change? */
9820 segdir
->res0c
= 0xf;
9823 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9827 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9830 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9834 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9836 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9837 base
->memoffset
+= file_len
;
9844 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9846 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9847 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9848 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9849 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9850 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9851 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9852 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9853 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9854 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9855 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9856 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9857 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9858 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9859 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9862 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9864 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9866 DWORD written
, junk_size
, junk_offs
, running_offset
;
9873 TRACE("%p\n", This
);
9875 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
9876 if(This
->typeinfos
[i
]->needs_layout
)
9877 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
9879 memset(&file
, 0, sizeof(file
));
9881 file
.header
.magic1
= 0x5446534D;
9882 file
.header
.magic2
= 0x00010002;
9883 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9884 file
.header
.lcid2
= This
->set_lcid
;
9885 file
.header
.varflags
= 0x40 | This
->syskind
;
9887 file
.header
.varflags
|= 0x10;
9888 if (This
->HelpStringDll
)
9889 file
.header
.varflags
|= HELPDLLFLAG
;
9890 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
9891 file
.header
.flags
= This
->libflags
;
9892 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9893 file
.header
.helpcontext
= This
->dwHelpContext
;
9894 file
.header
.res44
= 0x20;
9895 file
.header
.res48
= 0x80;
9896 file
.header
.dispatchpos
= This
->dispatch_href
;
9898 WMSFT_compile_namehash(This
, &file
);
9899 /* do name and string compilation to get offsets for other compilations */
9900 hres
= WMSFT_compile_names(This
, &file
);
9902 WMSFT_free_file(&file
);
9906 hres
= WMSFT_compile_strings(This
, &file
);
9908 WMSFT_free_file(&file
);
9912 WMSFT_compile_guidhash(This
, &file
);
9913 hres
= WMSFT_compile_guids(This
, &file
);
9915 WMSFT_free_file(&file
);
9920 file
.header
.helpfile
= This
->HelpFile
->offset
;
9922 file
.header
.helpfile
= -1;
9925 file
.header
.helpstring
= This
->DocString
->offset
;
9927 file
.header
.helpstring
= -1;
9929 /* do some more segment compilation */
9930 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9931 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9934 file
.header
.NameOffset
= This
->Name
->offset
;
9936 file
.header
.NameOffset
= -1;
9938 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
9941 file
.header
.posguid
= This
->guid
->offset
;
9943 file
.header
.posguid
= -1;
9945 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9946 if(file
.header
.varflags
& HELPDLLFLAG
)
9947 junk_size
+= sizeof(DWORD
);
9949 junk
= heap_alloc_zero(junk_size
);
9950 if(file
.header
.varflags
& HELPDLLFLAG
){
9951 *junk
= This
->HelpStringDll
->offset
;
9960 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
9961 WMSFT_compile_impinfo(This
, &file
);
9965 TRACE("header at: 0x%x\n", running_offset
);
9966 running_offset
+= sizeof(file
.header
);
9968 TRACE("junk at: 0x%x\n", running_offset
);
9969 running_offset
+= junk_size
;
9971 TRACE("segdir at: 0x%x\n", running_offset
);
9972 running_offset
+= sizeof(file
.segdir
);
9974 TRACE("typeinfo at: 0x%x\n", running_offset
);
9975 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
9977 TRACE("guidhashtab at: 0x%x\n", running_offset
);
9978 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
9980 TRACE("guidtab at: 0x%x\n", running_offset
);
9981 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
9983 TRACE("reftab at: 0x%x\n", running_offset
);
9984 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
9986 TRACE("impinfo at: 0x%x\n", running_offset
);
9987 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
9989 TRACE("impfiles at: 0x%x\n", running_offset
);
9990 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
9992 TRACE("namehashtab at: 0x%x\n", running_offset
);
9993 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
9995 TRACE("nametab at: 0x%x\n", running_offset
);
9996 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
9998 TRACE("stringtab at: 0x%x\n", running_offset
);
9999 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10001 TRACE("typdesc at: 0x%x\n", running_offset
);
10002 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10004 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10005 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10007 TRACE("custdata at: 0x%x\n", running_offset
);
10008 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10010 TRACE("cdguids at: 0x%x\n", running_offset
);
10011 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10013 TRACE("res0e at: 0x%x\n", running_offset
);
10014 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10016 TRACE("res0f at: 0x%x\n", running_offset
);
10017 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10019 TRACE("aux_seg at: 0x%x\n", running_offset
);
10021 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10023 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10024 FILE_ATTRIBUTE_NORMAL
, 0);
10025 if (outfile
== INVALID_HANDLE_VALUE
){
10026 WMSFT_free_file(&file
);
10028 return TYPE_E_IOERROR
;
10031 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10033 WMSFT_free_file(&file
);
10034 CloseHandle(outfile
);
10036 return TYPE_E_IOERROR
;
10039 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10042 WMSFT_free_file(&file
);
10043 CloseHandle(outfile
);
10044 return TYPE_E_IOERROR
;
10047 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10049 WMSFT_free_file(&file
);
10050 CloseHandle(outfile
);
10051 return TYPE_E_IOERROR
;
10054 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10055 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10056 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10057 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10058 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10059 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10060 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10061 WMSFT_write_segment(outfile
, &file
.name_seg
);
10062 WMSFT_write_segment(outfile
, &file
.string_seg
);
10063 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10064 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10065 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10066 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10067 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10069 WMSFT_free_file(&file
);
10071 CloseHandle(outfile
);
10076 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10079 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10080 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10084 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10085 REFGUID guid
, VARIANT
*varVal
)
10087 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10088 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
10092 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10093 ULONG helpStringContext
)
10095 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10096 FIXME("%p %u - stub\n", This
, helpStringContext
);
10100 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10103 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10104 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10107 return E_INVALIDARG
;
10109 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10114 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10115 ICreateTypeLib2_fnQueryInterface
,
10116 ICreateTypeLib2_fnAddRef
,
10117 ICreateTypeLib2_fnRelease
,
10118 ICreateTypeLib2_fnCreateTypeInfo
,
10119 ICreateTypeLib2_fnSetName
,
10120 ICreateTypeLib2_fnSetVersion
,
10121 ICreateTypeLib2_fnSetGuid
,
10122 ICreateTypeLib2_fnSetDocString
,
10123 ICreateTypeLib2_fnSetHelpFileName
,
10124 ICreateTypeLib2_fnSetHelpContext
,
10125 ICreateTypeLib2_fnSetLcid
,
10126 ICreateTypeLib2_fnSetLibFlags
,
10127 ICreateTypeLib2_fnSaveAllChanges
,
10128 ICreateTypeLib2_fnDeleteTypeInfo
,
10129 ICreateTypeLib2_fnSetCustData
,
10130 ICreateTypeLib2_fnSetHelpStringContext
,
10131 ICreateTypeLib2_fnSetHelpStringDll
10134 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10135 REFIID riid
, void **object
)
10137 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10139 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10142 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10144 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10146 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10149 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10151 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10153 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10156 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10159 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10161 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10163 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10168 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10171 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10175 TRACE("%p %x\n", This
, typeFlags
);
10177 if (typeFlags
& TYPEFLAG_FDUAL
) {
10178 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10180 ITypeInfo
*dispatch
;
10184 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10188 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10189 ITypeLib_Release(stdole
);
10193 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10194 ITypeInfo_Release(dispatch
);
10199 old_flags
= This
->wTypeFlags
;
10200 This
->wTypeFlags
= typeFlags
;
10202 hres
= ICreateTypeInfo2_LayOut(iface
);
10203 if (FAILED(hres
)) {
10204 This
->wTypeFlags
= old_flags
;
10211 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10214 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10216 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10219 return E_INVALIDARG
;
10221 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10226 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10229 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10231 TRACE("%p %d\n", This
, helpContext
);
10233 This
->dwHelpContext
= helpContext
;
10238 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10239 WORD majorVerNum
, WORD minorVerNum
)
10241 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10243 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10245 This
->wMajorVerNum
= majorVerNum
;
10246 This
->wMinorVerNum
= minorVerNum
;
10251 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10252 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10254 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10256 ITypeLib
*container
;
10257 TLBRefType
*ref_type
;
10259 TYPEATTR
*typeattr
;
10263 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10265 if (!typeInfo
|| !refType
)
10266 return E_INVALIDARG
;
10268 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10272 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10273 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10275 ITypeLib_Release(container
);
10277 *refType
= target
->hreftype
;
10282 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10283 if (FAILED(hres
)) {
10284 ITypeLib_Release(container
);
10288 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10289 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10290 implib
->lcid
== libattr
->lcid
&&
10291 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10292 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10296 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10297 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10299 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10300 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10301 implib
->name
= SysAllocString(our_container
->path
);
10303 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10304 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10306 implib
->name
= NULL
;
10307 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10311 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10312 implib
->lcid
= libattr
->lcid
;
10313 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10314 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10316 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10319 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10320 ITypeLib_Release(container
);
10322 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10327 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10328 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10329 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10330 ref_type
->tkind
== typeattr
->typekind
)
10335 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10336 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10338 ref_type
->tkind
= typeattr
->typekind
;
10339 ref_type
->pImpTLInfo
= implib
;
10340 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10342 ref_type
->index
= TLB_REF_USE_GUID
;
10344 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10346 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10349 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10351 *refType
= ref_type
->reference
| 0x1;
10353 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10354 This
->pTypeLib
->dispatch_href
= *refType
;
10359 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10360 UINT index
, FUNCDESC
*funcDesc
)
10362 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10363 TLBFuncDesc tmp_func_desc
, *func_desc
;
10368 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10370 if (!funcDesc
|| funcDesc
->oVft
& 3)
10371 return E_INVALIDARG
;
10373 switch (This
->typekind
) {
10375 if (funcDesc
->funckind
!= FUNC_STATIC
)
10376 return TYPE_E_BADMODULEKIND
;
10378 case TKIND_DISPATCH
:
10379 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10380 return TYPE_E_BADMODULEKIND
;
10383 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10384 return TYPE_E_BADMODULEKIND
;
10387 if (index
> This
->cFuncs
)
10388 return TYPE_E_ELEMENTNOTFOUND
;
10390 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10391 !funcDesc
->cParams
)
10392 return TYPE_E_INCONSISTENTPROPFUNCS
;
10395 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10396 funcDesc
->oVft
% 8 != 0)
10397 return E_INVALIDARG
;
10400 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10401 TLBFuncDesc_Constructor(&tmp_func_desc
);
10403 tmp_func_desc
.funcdesc
= *funcDesc
;
10405 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10406 tmp_func_desc
.funcdesc
.oVft
|= 1;
10408 if (funcDesc
->cScodes
) {
10409 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10410 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10412 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10414 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10415 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10416 buf_size
+= sizeof(ELEMDESC
);
10417 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10419 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10420 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10422 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10423 if (FAILED(hres
)) {
10424 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10425 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10429 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10430 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10431 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10432 if (FAILED(hres
)) {
10433 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10434 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10437 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10438 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10439 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10440 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10441 if (FAILED(hres
)) {
10442 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10443 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10449 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10451 if (This
->funcdescs
) {
10452 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10453 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10455 if (index
< This
->cFuncs
) {
10456 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10457 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10458 func_desc
= This
->funcdescs
+ index
;
10460 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10462 /* move custdata lists to the new memory location */
10463 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10465 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10466 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10467 list_init(&fd
->custdata_list
);
10469 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10470 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10475 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10477 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10478 list_init(&func_desc
->custdata_list
);
10482 This
->needs_layout
= TRUE
;
10487 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10488 UINT index
, HREFTYPE refType
)
10490 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10491 TLBImplType
*impl_type
;
10494 TRACE("%p %u %d\n", This
, index
, refType
);
10496 switch(This
->typekind
){
10497 case TKIND_COCLASS
: {
10499 FIXME("Unhandled index: -1\n");
10503 if(index
!= This
->cImplTypes
)
10504 return TYPE_E_ELEMENTNOTFOUND
;
10508 case TKIND_INTERFACE
:
10509 case TKIND_DISPATCH
:
10510 if (index
!= 0 || This
->cImplTypes
)
10511 return TYPE_E_ELEMENTNOTFOUND
;
10514 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10518 if (This
->impltypes
){
10521 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10522 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10524 if (index
< This
->cImplTypes
) {
10525 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10526 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10527 impl_type
= This
->impltypes
+ index
;
10529 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10531 /* move custdata lists to the new memory location */
10532 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10534 TLBImplType
*it
= &This
->impltypes
[i
];
10535 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10536 list_init(&it
->custdata_list
);
10538 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10539 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10544 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10546 memset(impl_type
, 0, sizeof(TLBImplType
));
10547 TLBImplType_Constructor(impl_type
);
10548 impl_type
->hRef
= refType
;
10550 ++This
->cImplTypes
;
10552 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10553 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10555 hres
= ICreateTypeInfo2_LayOut(iface
);
10562 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10563 UINT index
, INT implTypeFlags
)
10565 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10566 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10568 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10570 if (This
->typekind
!= TKIND_COCLASS
)
10571 return TYPE_E_BADMODULEKIND
;
10573 if (index
>= This
->cImplTypes
)
10574 return TYPE_E_ELEMENTNOTFOUND
;
10576 impl_type
->implflags
= implTypeFlags
;
10581 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10584 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10586 TRACE("%p %d\n", This
, alignment
);
10588 This
->cbAlignment
= alignment
;
10593 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10596 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10598 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10601 return E_INVALIDARG
;
10603 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10605 This
->lpstrSchema
= This
->Schema
->str
;
10610 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10611 UINT index
, VARDESC
*varDesc
)
10613 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10614 TLBVarDesc
*var_desc
;
10616 TRACE("%p %u %p\n", This
, index
, varDesc
);
10618 if (This
->vardescs
){
10621 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10622 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10624 if (index
< This
->cVars
) {
10625 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10626 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10627 var_desc
= This
->vardescs
+ index
;
10629 var_desc
= This
->vardescs
+ This
->cVars
;
10631 /* move custdata lists to the new memory location */
10632 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10634 TLBVarDesc
*var
= &This
->vardescs
[i
];
10635 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10636 list_init(&var
->custdata_list
);
10638 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10639 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10644 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10646 TLBVarDesc_Constructor(var_desc
);
10647 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10648 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10652 This
->needs_layout
= TRUE
;
10657 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10658 UINT index
, LPOLESTR
*names
, UINT numNames
)
10660 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10661 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10664 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10667 return E_INVALIDARG
;
10669 if (index
>= This
->cFuncs
|| numNames
== 0)
10670 return TYPE_E_ELEMENTNOTFOUND
;
10672 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10673 if(numNames
> func_desc
->funcdesc
.cParams
)
10674 return TYPE_E_ELEMENTNOTFOUND
;
10676 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10677 return TYPE_E_ELEMENTNOTFOUND
;
10679 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10680 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10681 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10682 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10683 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10684 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10686 return TYPE_E_AMBIGUOUSNAME
;
10690 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10692 for (i
= 1; i
< numNames
; ++i
) {
10693 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10694 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10700 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10701 UINT index
, LPOLESTR name
)
10703 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10705 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10708 return E_INVALIDARG
;
10710 if(index
>= This
->cVars
)
10711 return TYPE_E_ELEMENTNOTFOUND
;
10713 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10717 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10718 TYPEDESC
*tdescAlias
)
10720 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10723 TRACE("%p %p\n", This
, tdescAlias
);
10726 return E_INVALIDARG
;
10728 if(This
->typekind
!= TKIND_ALIAS
)
10729 return TYPE_E_BADMODULEKIND
;
10731 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->cbSizeInstance
, &This
->cbAlignment
);
10735 heap_free(This
->tdescAlias
);
10736 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10737 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10742 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10743 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10745 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10746 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10750 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10751 UINT index
, LPOLESTR docString
)
10753 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10754 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10756 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10759 return E_INVALIDARG
;
10761 if(index
>= This
->cFuncs
)
10762 return TYPE_E_ELEMENTNOTFOUND
;
10764 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10769 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10770 UINT index
, LPOLESTR docString
)
10772 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10773 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10775 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10778 return E_INVALIDARG
;
10780 if(index
>= This
->cVars
)
10781 return TYPE_E_ELEMENTNOTFOUND
;
10783 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10788 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10789 UINT index
, DWORD helpContext
)
10791 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10792 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10794 TRACE("%p %u %d\n", This
, index
, helpContext
);
10796 if(index
>= This
->cFuncs
)
10797 return TYPE_E_ELEMENTNOTFOUND
;
10799 func_desc
->helpcontext
= helpContext
;
10804 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10805 UINT index
, DWORD helpContext
)
10807 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10808 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10810 TRACE("%p %u %d\n", This
, index
, helpContext
);
10812 if(index
>= This
->cVars
)
10813 return TYPE_E_ELEMENTNOTFOUND
;
10815 var_desc
->HelpContext
= helpContext
;
10820 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10821 UINT index
, BSTR bstrMops
)
10823 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10824 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10828 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10831 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10833 TRACE("%p %p\n", This
, idlDesc
);
10836 return E_INVALIDARG
;
10838 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10839 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10844 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10846 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10848 TLBFuncDesc
*func_desc
;
10849 UINT user_vft
= 0, i
, depth
= 0;
10850 HRESULT hres
= S_OK
;
10852 TRACE("%p\n", This
);
10854 This
->needs_layout
= FALSE
;
10856 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10860 if (This
->typekind
== TKIND_INTERFACE
) {
10865 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10867 if (SUCCEEDED(hres
)) {
10868 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10870 if (SUCCEEDED(hres
)) {
10871 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10872 if (FAILED(hres
)) {
10873 ITypeInfo_Release(inh
);
10874 ITypeInfo_Release(tinfo
);
10877 This
->cbSizeVft
= attr
->cbSizeVft
;
10878 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10882 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10883 if(SUCCEEDED(hres
)){
10885 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10886 if(SUCCEEDED(hres
)){
10887 ITypeInfo_Release(inh
);
10891 }while(SUCCEEDED(hres
));
10894 ITypeInfo_Release(inh
);
10895 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10896 This
->cbSizeVft
= 0;
10899 ITypeInfo_Release(tinfo
);
10902 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10903 This
->cbSizeVft
= 0;
10906 ITypeInfo_Release(tinfo
);
10909 } else if (This
->typekind
== TKIND_DISPATCH
)
10910 This
->cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10912 This
->cbSizeVft
= 0;
10914 func_desc
= This
->funcdescs
;
10916 while (i
< This
->cFuncs
) {
10917 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10918 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
10920 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10921 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10923 This
->cbSizeVft
+= This
->pTypeLib
->ptr_size
;
10925 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10928 BOOL reset
= FALSE
;
10930 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10932 iter
= This
->funcdescs
;
10933 while (j
< This
->cFuncs
) {
10934 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10936 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
10939 ++func_desc
->funcdesc
.memid
;
10940 iter
= This
->funcdescs
;
10953 if (user_vft
> This
->cbSizeVft
)
10954 This
->cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
10956 for(i
= 0; i
< This
->cVars
; ++i
){
10957 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
10958 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
10960 BOOL reset
= FALSE
;
10963 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
10965 iter
= This
->vardescs
;
10966 while (j
< This
->cVars
) {
10967 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
10969 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->cVars
;
10972 ++var_desc
->vardesc
.memid
;
10973 iter
= This
->vardescs
;
10983 ITypeInfo_Release(tinfo
);
10987 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
10990 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10991 FIXME("%p %u - stub\n", This
, index
);
10995 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
10996 MEMBERID memid
, INVOKEKIND invKind
)
10998 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10999 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11003 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11006 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11007 FIXME("%p %u - stub\n", This
, index
);
11011 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11014 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11015 FIXME("%p %x - stub\n", This
, memid
);
11019 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11022 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11023 FIXME("%p %u - stub\n", This
, index
);
11027 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11028 REFGUID guid
, VARIANT
*varVal
)
11032 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11034 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11036 if (!guid
|| !varVal
)
11037 return E_INVALIDARG
;
11039 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11041 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11044 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11045 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11047 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11048 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11052 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11053 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11055 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11056 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11060 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11061 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11063 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11064 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11068 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11069 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11071 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11072 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11076 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11077 ULONG helpStringContext
)
11079 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11081 TRACE("%p %u\n", This
, helpStringContext
);
11083 This
->dwHelpStringContext
= helpStringContext
;
11088 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11089 UINT index
, ULONG helpStringContext
)
11091 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11092 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11096 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11097 UINT index
, ULONG helpStringContext
)
11099 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11100 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11104 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11106 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11107 FIXME("%p - stub\n", This
);
11111 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11114 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11116 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11119 return E_INVALIDARG
;
11121 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11126 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11127 ICreateTypeInfo2_fnQueryInterface
,
11128 ICreateTypeInfo2_fnAddRef
,
11129 ICreateTypeInfo2_fnRelease
,
11130 ICreateTypeInfo2_fnSetGuid
,
11131 ICreateTypeInfo2_fnSetTypeFlags
,
11132 ICreateTypeInfo2_fnSetDocString
,
11133 ICreateTypeInfo2_fnSetHelpContext
,
11134 ICreateTypeInfo2_fnSetVersion
,
11135 ICreateTypeInfo2_fnAddRefTypeInfo
,
11136 ICreateTypeInfo2_fnAddFuncDesc
,
11137 ICreateTypeInfo2_fnAddImplType
,
11138 ICreateTypeInfo2_fnSetImplTypeFlags
,
11139 ICreateTypeInfo2_fnSetAlignment
,
11140 ICreateTypeInfo2_fnSetSchema
,
11141 ICreateTypeInfo2_fnAddVarDesc
,
11142 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11143 ICreateTypeInfo2_fnSetVarName
,
11144 ICreateTypeInfo2_fnSetTypeDescAlias
,
11145 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11146 ICreateTypeInfo2_fnSetFuncDocString
,
11147 ICreateTypeInfo2_fnSetVarDocString
,
11148 ICreateTypeInfo2_fnSetFuncHelpContext
,
11149 ICreateTypeInfo2_fnSetVarHelpContext
,
11150 ICreateTypeInfo2_fnSetMops
,
11151 ICreateTypeInfo2_fnSetTypeIdldesc
,
11152 ICreateTypeInfo2_fnLayOut
,
11153 ICreateTypeInfo2_fnDeleteFuncDesc
,
11154 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11155 ICreateTypeInfo2_fnDeleteVarDesc
,
11156 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11157 ICreateTypeInfo2_fnDeleteImplType
,
11158 ICreateTypeInfo2_fnSetCustData
,
11159 ICreateTypeInfo2_fnSetFuncCustData
,
11160 ICreateTypeInfo2_fnSetParamCustData
,
11161 ICreateTypeInfo2_fnSetVarCustData
,
11162 ICreateTypeInfo2_fnSetImplTypeCustData
,
11163 ICreateTypeInfo2_fnSetHelpStringContext
,
11164 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11165 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11166 ICreateTypeInfo2_fnInvalidate
,
11167 ICreateTypeInfo2_fnSetName
11170 /******************************************************************************
11171 * ClearCustData (OLEAUT32.171)
11173 * Clear a custom data type's data.
11176 * lpCust [I] The custom data type instance
11181 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11183 if (lpCust
&& lpCust
->cCustData
)
11185 if (lpCust
->prgCustData
)
11189 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11190 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11192 CoTaskMemFree(lpCust
->prgCustData
);
11193 lpCust
->prgCustData
= NULL
;
11195 lpCust
->cCustData
= 0;