4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
44 * -. lousy fatal error handling
49 #include "wine/port.h"
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
69 #include "wine/unicode.h"
72 #include "wine/debug.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
91 WORD type_id
; /* Type identifier */
92 WORD count
; /* Number of resources of this type */
93 DWORD resloader
; /* SetResourceHandler() */
99 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
100 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
102 /****************************************************************************
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
108 #ifdef WORDS_BIGENDIAN
109 static WORD
FromLEWord(WORD p_iVal
)
111 return (((p_iVal
& 0x00FF) << 8) |
112 ((p_iVal
& 0xFF00) >> 8));
116 static DWORD
FromLEDWord(DWORD p_iVal
)
118 return (((p_iVal
& 0x000000FF) << 24) |
119 ((p_iVal
& 0x0000FF00) << 8) |
120 ((p_iVal
& 0x00FF0000) >> 8) |
121 ((p_iVal
& 0xFF000000) >> 24));
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val
, int p_iSize
)
141 p_iSize
/= sizeof(WORD
);
144 *Val
= FromLEWord(*Val
);
151 static void FromLEDWords(void *p_Val
, int p_iSize
)
155 p_iSize
/= sizeof(DWORD
);
158 *Val
= FromLEDWord(*Val
);
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
169 * Find a typelib key which matches a requested maj.min version.
171 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
173 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
177 INT best_maj
= -1, best_min
= -1;
180 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
181 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
186 len
= sizeof(key_name
);
188 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
192 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
196 if (*wMaj
== 0xffff && *wMin
== 0xffff)
198 if (v_maj
> best_maj
) best_maj
= v_maj
;
199 if (v_min
> best_min
) best_min
= v_min
;
201 else if (*wMaj
== v_maj
)
208 break; /* exact match */
210 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
213 len
= sizeof(key_name
);
217 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
219 if (*wMaj
== 0xffff && *wMin
== 0xffff)
221 if (best_maj
>= 0 && best_min
>= 0)
229 if (*wMaj
== best_maj
&& best_min
>= 0)
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
241 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
242 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
244 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
245 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
246 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
250 /* get the path of an interface key, in the form "Interface\\<guid>" */
251 /* buffer must be at least 50 characters long */
252 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
254 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
256 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
257 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
261 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
262 /* buffer must be at least 16 characters long */
263 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
265 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
266 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
267 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
268 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
270 sprintfW( buffer
, LcidFormatW
, lcid
);
273 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
274 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
275 case SYS_WIN64
: strcatW( buffer
, win64W
); break;
277 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
283 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
286 /****************************************************************************
287 * QueryPathOfRegTypeLib [OLEAUT32.164]
289 * Gets the path to a registered type library.
292 * guid [I] referenced guid
293 * wMaj [I] major version
294 * wMin [I] minor version
296 * path [O] path of typelib
300 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
301 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
304 HRESULT WINAPI
QueryPathOfRegTypeLib(
311 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
315 WCHAR Path
[MAX_PATH
];
318 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
320 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
321 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
323 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
324 if (res
== ERROR_FILE_NOT_FOUND
)
326 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
327 return TYPE_E_LIBNOTREGISTERED
;
329 else if (res
!= ERROR_SUCCESS
)
331 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
332 return TYPE_E_REGISTRYACCESS
;
337 LONG dwPathLen
= sizeof(Path
);
339 get_lcid_subkey( myLCID
, SYS_WIN32
, buffer
);
341 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
345 else if (myLCID
== lcid
)
347 /* try with sub-langid */
348 myLCID
= SUBLANGID(lcid
);
350 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
352 /* try with system langid */
362 *path
= SysAllocString( Path
);
367 TRACE_(typelib
)("-- 0x%08x\n", hr
);
371 /******************************************************************************
372 * CreateTypeLib [OLEAUT32.160] creates a typelib
378 HRESULT WINAPI
CreateTypeLib(
379 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
381 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
385 /******************************************************************************
386 * LoadTypeLib [OLEAUT32.161]
388 * Loads a type library
391 * szFile [I] Name of file to load from.
392 * pptLib [O] Pointer that receives ITypeLib object on success.
399 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
401 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
403 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
404 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
407 /******************************************************************************
408 * LoadTypeLibEx [OLEAUT32.183]
410 * Loads and optionally registers a type library
416 HRESULT WINAPI
LoadTypeLibEx(
417 LPCOLESTR szFile
, /* [in] Name of file to load from */
418 REGKIND regkind
, /* [in] Specify kind of registration */
419 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
421 WCHAR szPath
[MAX_PATH
+1];
424 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
428 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
433 case REGKIND_DEFAULT
:
434 /* don't register typelibs supplied with full path. Experimentation confirms the following */
435 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
436 (szFile
[0] && (szFile
[1] == ':'))) break;
437 /* else fall-through */
439 case REGKIND_REGISTER
:
440 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
442 IUnknown_Release(*pptLib
);
450 TRACE(" returns %08x\n",res
);
454 /******************************************************************************
455 * LoadRegTypeLib [OLEAUT32.162]
457 * Loads a registered type library.
460 * rguid [I] GUID of the registered type library.
461 * wVerMajor [I] major version.
462 * wVerMinor [I] minor version.
463 * lcid [I] locale ID.
464 * ppTLib [O] pointer that receives an ITypeLib object on success.
468 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
471 HRESULT WINAPI
LoadRegTypeLib(
483 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
487 res
= LoadTypeLib(bstr
, ppTLib
);
491 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
497 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
498 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
499 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
500 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
501 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
502 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
504 /******************************************************************************
505 * RegisterTypeLib [OLEAUT32.163]
506 * Adds information about a type library to the System Registry
508 * Docs: ITypeLib FAR * ptlib
509 * Docs: OLECHAR FAR* szFullPath
510 * Docs: OLECHAR FAR* szHelpDir
516 HRESULT WINAPI
RegisterTypeLib(
517 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
518 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
519 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
522 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
523 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
524 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
534 if (ptlib
== NULL
|| szFullPath
== NULL
)
537 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
541 if (attr
->syskind
!= SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
543 if (attr
->syskind
!= SYS_WIN32
&& attr
->syskind
!= SYS_WIN16
) return TYPE_E_BADMODULEKIND
;
546 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
549 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
550 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
554 /* Set the human-readable name of the typelib */
555 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
557 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
558 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
566 /* Make up the name of the typelib path subkey */
567 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
569 /* Create the typelib path subkey */
570 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
571 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
573 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
574 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
582 /* Create the flags subkey */
583 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
584 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
586 /* FIXME: is %u correct? */
587 static const WCHAR formatW
[] = {'%','u',0};
589 sprintfW(buf
, formatW
, attr
->wLibFlags
);
590 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
591 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
599 /* create the helpdir subkey */
600 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
601 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
603 BOOL freeHelpDir
= FALSE
;
606 /* if we created a new key, and helpDir was null, set the helpdir
607 to the directory which contains the typelib. However,
608 if we just opened an existing key, we leave the helpdir alone */
609 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
610 szHelpDir
= SysAllocString(szFullPath
);
611 pIndexStr
= strrchrW(szHelpDir
, '\\');
618 /* if we have an szHelpDir, set it! */
619 if (szHelpDir
!= NULL
) {
620 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
621 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
627 if (freeHelpDir
) SysFreeString(szHelpDir
);
639 /* register OLE Automation-compatible interfaces for this typelib */
640 types
= ITypeLib_GetTypeInfoCount(ptlib
);
641 for (tidx
=0; tidx
<types
; tidx
++) {
642 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
643 LPOLESTR name
= NULL
;
644 ITypeInfo
*tinfo
= NULL
;
646 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
649 case TKIND_INTERFACE
:
650 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
651 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
655 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
656 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
660 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
665 TYPEATTR
*tattr
= NULL
;
666 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
669 TRACE_(typelib
)("guid=%s, flags=%04x (",
670 debugstr_guid(&tattr
->guid
),
673 if (TRACE_ON(typelib
)) {
674 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
694 if (tattr
->wTypeFlags
& (TYPEFLAG_FOLEAUTOMATION
|TYPEFLAG_FDUAL
|TYPEFLAG_FDISPATCHABLE
))
696 /* register interface<->typelib coupling */
697 get_interface_key( &tattr
->guid
, keyName
);
698 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
699 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
702 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
703 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
705 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
706 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
707 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
708 (const BYTE
*)PSOA
, sizeof PSOA
);
712 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
713 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
714 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
715 (const BYTE
*)PSOA
, sizeof PSOA
);
719 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
720 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
723 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
724 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
726 StringFromGUID2(&attr
->guid
, buffer
, 40);
727 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
728 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
729 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
730 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
731 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
739 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
742 ITypeInfo_Release(tinfo
);
749 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
755 /******************************************************************************
756 * UnRegisterTypeLib [OLEAUT32.186]
757 * Removes information about a type library from the System Registry
764 HRESULT WINAPI
UnRegisterTypeLib(
765 REFGUID libid
, /* [in] Guid of the library */
766 WORD wVerMajor
, /* [in] major version */
767 WORD wVerMinor
, /* [in] minor version */
768 LCID lcid
, /* [in] locale id */
771 BSTR tlibPath
= NULL
;
774 WCHAR subKeyName
[50];
777 BOOL deleteOtherStuff
;
780 TYPEATTR
* typeAttr
= NULL
;
782 ITypeInfo
* typeInfo
= NULL
;
783 ITypeLib
* typeLib
= NULL
;
786 TRACE("(IID: %s)\n",debugstr_guid(libid
));
788 /* Create the path to the key */
789 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
791 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
793 TRACE("Unsupported syskind %i\n", syskind
);
794 result
= E_INVALIDARG
;
798 /* get the path to the typelib on disk */
799 if (QueryPathOfRegTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, &tlibPath
) != S_OK
) {
800 result
= E_INVALIDARG
;
804 /* Try and open the key to the type library. */
805 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
806 result
= E_INVALIDARG
;
810 /* Try and load the type library */
811 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
)) {
812 result
= TYPE_E_INVALIDSTATE
;
816 /* remove any types registered with this typelib */
817 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
818 for (i
=0; i
<numTypes
; i
++) {
819 /* get the kind of type */
820 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
824 /* skip non-interfaces, and get type info for the type */
825 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
828 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
831 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
835 /* the path to the type */
836 get_interface_key( &typeAttr
->guid
, subKeyName
);
838 /* Delete its bits */
839 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != ERROR_SUCCESS
) {
842 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
843 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
844 RegDeleteKeyW(subKey
, TypeLibW
);
847 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
850 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
852 if (typeInfo
) ITypeInfo_Release(typeInfo
);
856 /* Now, delete the type library path subkey */
857 get_lcid_subkey( lcid
, syskind
, subKeyName
);
858 RegDeleteKeyW(key
, subKeyName
);
859 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
860 RegDeleteKeyW(key
, subKeyName
);
862 /* check if there is anything besides the FLAGS/HELPDIR keys.
863 If there is, we don't delete them */
864 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
865 deleteOtherStuff
= TRUE
;
867 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
868 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
870 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
871 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
872 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
873 deleteOtherStuff
= FALSE
;
877 /* only delete the other parts of the key if we're absolutely sure */
878 if (deleteOtherStuff
) {
879 RegDeleteKeyW(key
, FLAGSW
);
880 RegDeleteKeyW(key
, HELPDIRW
);
884 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
885 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
886 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
890 SysFreeString(tlibPath
);
891 if (typeLib
) ITypeLib_Release(typeLib
);
892 if (subKey
) RegCloseKey(subKey
);
893 if (key
) RegCloseKey(key
);
897 /*======================= ITypeLib implementation =======================*/
899 typedef struct tagTLBCustData
903 struct tagTLBCustData
* next
;
906 /* data structure for import typelibs */
907 typedef struct tagTLBImpLib
909 int offset
; /* offset in the file (MSFT)
910 offset in nametable (SLTG)
911 just used to identify library while reading
913 GUID guid
; /* libid */
914 BSTR name
; /* name */
916 LCID lcid
; /* lcid of imported typelib */
918 WORD wVersionMajor
; /* major version number */
919 WORD wVersionMinor
; /* minor version number */
921 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
922 NULL if not yet loaded */
923 struct tagTLBImpLib
* next
;
926 /* internal ITypeLib data */
927 typedef struct tagITypeLibImpl
929 const ITypeLib2Vtbl
*lpVtbl
;
930 const ITypeCompVtbl
*lpVtblTypeComp
;
932 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
935 /* strings can be stored in tlb as multibyte strings BUT they are *always*
936 * exported to the application as a UNICODE string.
943 int TypeInfoCount
; /* nr of typeinfo's in librarry */
944 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
945 int ctCustData
; /* number of items in cust data list */
946 TLBCustData
* pCustData
; /* linked list to cust data */
947 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
948 int ctTypeDesc
; /* number of items in type desc array */
949 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
950 library. Only used while reading MSFT
952 struct list ref_list
; /* list of ref types in this typelib */
953 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
956 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
957 struct tagITypeLibImpl
*next
, *prev
;
962 static const ITypeLib2Vtbl tlbvt
;
963 static const ITypeCompVtbl tlbtcvt
;
965 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
967 return (ITypeLibImpl
*)((char*)iface
- FIELD_OFFSET(ITypeLibImpl
, lpVtblTypeComp
));
970 /* ITypeLib methods */
971 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
972 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
974 /*======================= ITypeInfo implementation =======================*/
976 /* data for referenced types */
977 typedef struct tagTLBRefType
979 INT index
; /* Type index for internal ref or for external ref
980 it the format is SLTG. -2 indicates to
983 GUID guid
; /* guid of the referenced type */
984 /* if index == TLB_REF_USE_GUID */
986 HREFTYPE reference
; /* The href of this ref */
987 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
988 TLB_REF_INTERNAL for internal refs
989 TLB_REF_NOT_FOUND for broken refs */
994 #define TLB_REF_USE_GUID -2
996 #define TLB_REF_INTERNAL (void*)-2
997 #define TLB_REF_NOT_FOUND (void*)-1
999 /* internal Parameter data */
1000 typedef struct tagTLBParDesc
1004 TLBCustData
* pCustData
; /* linked list to cust data */
1007 /* internal Function data */
1008 typedef struct tagTLBFuncDesc
1010 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1011 BSTR Name
; /* the name of this function */
1012 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1014 int HelpStringContext
;
1016 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
1018 TLBCustData
* pCustData
; /* linked list to cust data; */
1019 struct tagTLBFuncDesc
* next
;
1022 /* internal Variable data */
1023 typedef struct tagTLBVarDesc
1025 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1026 BSTR Name
; /* the name of this variable */
1028 int HelpStringContext
; /* FIXME: where? */
1031 TLBCustData
* pCustData
;/* linked list to cust data; */
1032 struct tagTLBVarDesc
* next
;
1035 /* internal implemented interface data */
1036 typedef struct tagTLBImplType
1038 HREFTYPE hRef
; /* hRef of interface */
1039 int implflags
; /* IMPLFLAG_*s */
1041 TLBCustData
* pCustData
;/* linked list to custom data; */
1042 struct tagTLBImplType
*next
;
1045 /* internal TypeInfo data */
1046 typedef struct tagITypeInfoImpl
1048 const ITypeInfo2Vtbl
*lpVtbl
;
1049 const ITypeCompVtbl
*lpVtblTypeComp
;
1051 BOOL no_free_data
; /* don't free data structures */
1052 TYPEATTR TypeAttr
; /* _lots_ of type information. */
1053 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1054 int index
; /* index in this typelib; */
1055 HREFTYPE hreftype
; /* hreftype for app object binding */
1056 /* type libs seem to store the doc strings in ascii
1057 * so why should we do it in unicode?
1062 DWORD dwHelpContext
;
1063 DWORD dwHelpStringContext
;
1066 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
1069 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
1071 /* Implemented Interfaces */
1072 TLBImplType
* impltypelist
;
1075 TLBCustData
* pCustData
; /* linked list to cust data; */
1076 struct tagITypeInfoImpl
* next
;
1079 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1081 return (ITypeInfoImpl
*)((char*)iface
- FIELD_OFFSET(ITypeInfoImpl
, lpVtblTypeComp
));
1084 static const ITypeInfo2Vtbl tinfvt
;
1085 static const ITypeCompVtbl tcompvt
;
1087 static ITypeInfo2
* ITypeInfo_Constructor(void);
1089 typedef struct tagTLBContext
1091 unsigned int oStart
; /* start of TLB in file */
1092 unsigned int pos
; /* current pos */
1093 unsigned int length
; /* total length */
1094 void *mapping
; /* memory mapping */
1095 MSFT_SegDir
* pTblDir
;
1096 ITypeLibImpl
* pLibInfo
;
1100 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
, int offset
);
1105 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1106 if (pTD
->vt
& VT_RESERVED
)
1107 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1108 if (pTD
->vt
& VT_BYREF
)
1109 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1110 if (pTD
->vt
& VT_ARRAY
)
1111 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1112 if (pTD
->vt
& VT_VECTOR
)
1113 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1114 switch(pTD
->vt
& VT_TYPEMASK
) {
1115 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1116 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1117 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1118 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1119 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1120 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1121 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1122 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1123 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1124 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1125 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1126 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1127 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1128 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1129 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1130 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1131 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1132 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1133 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1134 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1135 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1136 pTD
->u
.hreftype
); break;
1137 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1138 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1139 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1140 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1142 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1143 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1145 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1146 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1147 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1150 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1154 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1156 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1157 dump_TypeDesc(&edesc
->tdesc
,buf
);
1158 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1159 MESSAGE("\t\tu.paramdesc.wParamFlags");
1160 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1161 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1162 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1163 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1164 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1165 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1166 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1167 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1168 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1170 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1172 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1173 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1174 MESSAGE("Param %d:\n",i
);
1175 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1177 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1178 switch (funcdesc
->funckind
) {
1179 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1180 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1181 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1182 case FUNC_STATIC
: MESSAGE("static");break;
1183 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1184 default: MESSAGE("unknown");break;
1186 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1187 switch (funcdesc
->invkind
) {
1188 case INVOKE_FUNC
: MESSAGE("func");break;
1189 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1190 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1191 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1193 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1194 switch (funcdesc
->callconv
) {
1195 case CC_CDECL
: MESSAGE("cdecl");break;
1196 case CC_PASCAL
: MESSAGE("pascal");break;
1197 case CC_STDCALL
: MESSAGE("stdcall");break;
1198 case CC_SYSCALL
: MESSAGE("syscall");break;
1201 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1202 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1203 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1205 MESSAGE("\telemdescFunc (return value type):\n");
1206 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1209 static const char * const typekind_desc
[] =
1222 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1225 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1226 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1227 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1230 dump_FUNCDESC(&(pfd
->funcdesc
));
1232 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1233 MESSAGE("\tentry: %s\n", (pfd
->Entry
== (void *)-1) ? "invalid" : debugstr_w(pfd
->Entry
));
1235 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
)
1239 dump_TLBFuncDescOne(pfd
);
1243 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
)
1247 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1252 static void dump_TLBImpLib(const TLBImpLib
*import
)
1254 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1255 debugstr_w(import
->name
));
1256 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1257 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1260 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1264 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1266 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1267 if(ref
->index
== -1)
1268 TRACE_(typelib
)("%s\n", debugstr_guid(&(ref
->guid
)));
1270 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1272 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1274 TRACE_(typelib
)("in lib\n");
1275 dump_TLBImpLib(ref
->pImpTLInfo
);
1280 static void dump_TLBImplType(const TLBImplType
* impl
)
1284 "implementing/inheriting interface hRef = %x implflags %x\n",
1285 impl
->hRef
, impl
->implflags
);
1290 static void dump_Variant(const VARIANT
* pvar
)
1294 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1298 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1299 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1301 TRACE(",%p", V_BYREF(pvar
));
1303 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1305 TRACE(",%p", V_ARRAY(pvar
));
1307 else switch (V_TYPE(pvar
))
1309 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1310 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1311 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1312 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1314 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1316 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1317 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1318 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1319 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1320 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1321 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1322 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1323 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1324 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1325 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1326 V_CY(pvar
).s
.Lo
); break;
1328 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1329 TRACE(",<invalid>");
1331 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1332 st
.wHour
, st
.wMinute
, st
.wSecond
);
1336 case VT_USERDEFINED
:
1338 case VT_NULL
: break;
1339 default: TRACE(",?"); break;
1345 static void dump_DispParms(const DISPPARAMS
* pdp
)
1349 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1351 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1353 TRACE("named args:\n");
1354 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1355 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1358 if (pdp
->cArgs
&& pdp
->rgvarg
)
1361 for (index
= 0; index
< pdp
->cArgs
; index
++)
1362 dump_Variant( &pdp
->rgvarg
[index
] );
1366 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1368 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1369 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1370 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1371 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1372 TRACE("fct:%u var:%u impl:%u\n",
1373 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1374 TRACE("wTypeFlags: 0x%04x\n", pty
->TypeAttr
.wTypeFlags
);
1375 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1376 if (pty
->TypeAttr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(pty
->DllName
));
1378 dump_TLBFuncDesc(pty
->funclist
);
1379 dump_TLBVarDesc(pty
->varlist
);
1380 dump_TLBImplType(pty
->impltypelist
);
1383 static void dump_VARDESC(const VARDESC
*v
)
1385 MESSAGE("memid %d\n",v
->memid
);
1386 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1387 MESSAGE("oInst %d\n",v
->u
.oInst
);
1388 dump_ELEMDESC(&(v
->elemdescVar
));
1389 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1390 MESSAGE("varkind %d\n",v
->varkind
);
1393 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1395 /* VT_LPWSTR is largest type that */
1396 /* may appear in type description*/
1397 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1398 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1399 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1400 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1401 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1402 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1406 static void TLB_abort(void)
1411 static void * TLB_Alloc(unsigned size
) __WINE_ALLOC_SIZE(1);
1412 static void * TLB_Alloc(unsigned size
)
1415 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1417 ERR("cannot allocate memory\n");
1422 static void TLB_Free(void * ptr
)
1424 HeapFree(GetProcessHeap(), 0, ptr
);
1427 /* returns the size required for a deep copy of a typedesc into a
1429 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1433 if (alloc_initial_space
)
1434 size
+= sizeof(TYPEDESC
);
1440 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1443 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1444 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1450 /* deep copy a typedesc into a flat buffer */
1451 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1456 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1465 dest
->u
.lptdesc
= buffer
;
1466 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1469 dest
->u
.lpadesc
= buffer
;
1470 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1471 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1472 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1478 /* free custom data allocated by MSFT_CustData */
1479 static inline void TLB_FreeCustData(TLBCustData
*pCustData
)
1481 TLBCustData
*pCustDataNext
;
1482 for (; pCustData
; pCustData
= pCustDataNext
)
1484 VariantClear(&pCustData
->data
);
1486 pCustDataNext
= pCustData
->next
;
1487 TLB_Free(pCustData
);
1491 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1496 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1497 ret
= SysAllocStringLen(NULL
, len
- 1);
1498 if (!ret
) return ret
;
1499 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1503 /**********************************************************************
1505 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1507 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
1512 static inline void MSFT_Seek(TLBContext
*pcx
, long where
)
1514 if (where
!= DO_NOT_SEEK
)
1516 where
+= pcx
->oStart
;
1517 if (where
> pcx
->length
)
1520 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1528 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1530 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1531 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1533 MSFT_Seek(pcx
, where
);
1534 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1535 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1540 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1545 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1546 FromLEDWords(buffer
, ret
);
1551 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1556 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1557 FromLEWords(buffer
, ret
);
1562 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1564 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1565 memset(pGuid
,0, sizeof(GUID
));
1568 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1569 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1570 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1571 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1572 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1575 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
1577 MSFT_NameIntro niName
;
1581 ERR_(typelib
)("bad offset %d\n", offset
);
1585 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1586 pcx
->pTblDir
->pNametab
.offset
+offset
);
1588 return niName
.hreftype
;
1591 static BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1594 MSFT_NameIntro niName
;
1596 BSTR bstrName
= NULL
;
1600 ERR_(typelib
)("bad offset %d\n", offset
);
1603 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1604 pcx
->pTblDir
->pNametab
.offset
+offset
);
1605 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1606 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1607 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1608 name
[niName
.namelen
& 0xff]='\0';
1610 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1613 /* no invalid characters in string */
1616 bstrName
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1618 /* don't check for invalid character since this has been done previously */
1619 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, bstrName
, lengthInChars
);
1623 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1627 static BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1634 if(offset
<0) return NULL
;
1635 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1636 if(length
<= 0) return 0;
1637 string
=TLB_Alloc(length
+1);
1638 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1639 string
[length
]='\0';
1641 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1642 string
, -1, NULL
, 0);
1644 /* no invalid characters in string */
1647 bstr
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1649 /* don't check for invalid character since this has been done previously */
1650 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, bstr
, lengthInChars
);
1654 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1658 * read a value and fill a VARIANT structure
1660 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1664 TRACE_(typelib
)("\n");
1666 if(offset
<0) { /* data are packed in here */
1667 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1668 V_I4(pVar
) = offset
& 0x3ffffff;
1671 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1672 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1673 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1674 switch (V_VT(pVar
)){
1675 case VT_EMPTY
: /* FIXME: is this right? */
1676 case VT_NULL
: /* FIXME: is this right? */
1677 case VT_I2
: /* this should not happen */
1688 case VT_VOID
: /* FIXME: is this right? */
1696 case VT_DECIMAL
: /* FIXME: is this right? */
1699 /* pointer types with known behaviour */
1702 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1705 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
1708 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
1710 nullPos
= MSFT_Tell(pcx
);
1711 size
= nullPos
- origPos
;
1712 MSFT_Seek(pcx
, origPos
);
1714 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1715 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1716 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1717 /* FIXME: do we need a AtoW conversion here? */
1718 V_UNION(pVar
, bstrVal
[size
])='\0';
1719 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1723 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1730 case VT_USERDEFINED
:
1736 case VT_STREAMED_OBJECT
:
1737 case VT_STORED_OBJECT
:
1738 case VT_BLOB_OBJECT
:
1743 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1747 if(size
>0) /* (big|small) endian correct? */
1748 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1752 * create a linked list with custom data
1754 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1760 TRACE_(typelib
)("\n");
1764 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1765 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1766 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1767 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1768 /* add new custom data at head of the list */
1769 pNew
->next
=*ppCustData
;
1771 offset
= entry
.next
;
1776 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1780 pTd
->vt
=type
& VT_TYPEMASK
;
1782 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1784 if(pTd
->vt
== VT_USERDEFINED
)
1785 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, pTd
->u
.hreftype
);
1787 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1790 static void MSFT_ResolveReferencedTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, TYPEDESC
*lpTypeDesc
)
1792 /* resolve referenced type if any */
1795 switch (lpTypeDesc
->vt
)
1798 lpTypeDesc
= lpTypeDesc
->u
.lptdesc
;
1802 lpTypeDesc
= & (lpTypeDesc
->u
.lpadesc
->tdescElem
);
1805 case VT_USERDEFINED
:
1806 MSFT_DoRefType(pcx
, pTI
->pTypeLib
,
1807 lpTypeDesc
->u
.hreftype
);
1819 MSFT_DoFuncs(TLBContext
* pcx
,
1824 TLBFuncDesc
** pptfd
)
1827 * member information is stored in a data structure at offset
1828 * indicated by the memoffset field of the typeinfo structure
1829 * There are several distinctive parts.
1830 * The first part starts with a field that holds the total length
1831 * of this (first) part excluding this field. Then follow the records,
1832 * for each member there is one record.
1834 * The first entry is always the length of the record (including this
1836 * The rest of the record depends on the type of the member. If there is
1837 * a field indicating the member type (function, variable, interface, etc)
1838 * I have not found it yet. At this time we depend on the information
1839 * in the type info and the usual order how things are stored.
1841 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1844 * Third is an equal sized array with file offsets to the name entry
1847 * The fourth and last (?) part is an array with offsets to the records
1848 * in the first part of this file segment.
1851 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1852 int recoffset
= offset
+ sizeof(INT
);
1854 char *recbuf
= HeapAlloc(GetProcessHeap(), 0, 0xffff);
1855 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1856 TLBFuncDesc
*ptfd_prev
= NULL
;
1858 TRACE_(typelib
)("\n");
1860 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1862 for ( i
= 0; i
< cFuncs
; i
++ )
1864 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1866 /* name, eventually add to a hash table */
1867 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1868 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1870 /* nameoffset is sometimes -1 on the second half of a propget/propput
1871 * pair of functions */
1872 if ((nameoffset
== -1) && (i
> 0))
1873 (*pptfd
)->Name
= SysAllocString(ptfd_prev
->Name
);
1875 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1877 /* read the function information record */
1878 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1880 reclength
&= 0xffff;
1882 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1884 /* do the attributes */
1885 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1888 if ( nrattributes
> 0 )
1890 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1892 if ( nrattributes
> 1 )
1894 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1895 pFuncRec
->OptAttr
[1]) ;
1897 if ( nrattributes
> 2 )
1899 if ( pFuncRec
->FKCCIC
& 0x2000 )
1901 if (HIWORD(pFuncRec
->OptAttr
[2]) != 0)
1902 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec
->OptAttr
[2]);
1903 (*pptfd
)->Entry
= (BSTR
)pFuncRec
->OptAttr
[2];
1907 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1908 pFuncRec
->OptAttr
[2]);
1910 if( nrattributes
> 5 )
1912 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1914 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1917 pFuncRec
->OptAttr
[6],
1918 &(*pptfd
)->pCustData
);
1924 (*pptfd
)->Entry
= (BSTR
)-1;
1929 /* fill the FuncDesc Structure */
1930 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1931 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1933 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1934 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1935 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1936 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1937 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1938 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1939 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1943 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1945 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
);
1947 /* do the parameters/arguments */
1948 if(pFuncRec
->nrargs
)
1951 MSFT_ParameterInfo paraminfo
;
1953 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1954 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1956 (*pptfd
)->pParamDesc
=
1957 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1959 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1960 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1962 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1964 ELEMDESC
*elemdesc
= &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1971 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1974 if (paraminfo
.oName
== -1)
1975 /* this occurs for [propput] or [propget] methods, so
1976 * we should just set the name of the parameter to the
1977 * name of the method. */
1978 (*pptfd
)->pParamDesc
[j
].Name
= SysAllocString((*pptfd
)->Name
);
1980 (*pptfd
)->pParamDesc
[j
].Name
=
1981 MSFT_ReadName( pcx
, paraminfo
.oName
);
1982 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w((*pptfd
)->pParamDesc
[j
].Name
));
1984 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
1987 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
1988 (pFuncRec
->FKCCIC
& 0x1000) )
1990 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1992 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1994 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
1996 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1997 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1999 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2003 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2005 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
2008 pFuncRec
->OptAttr
[7+j
],
2009 &(*pptfd
)->pParamDesc
[j
].pCustData
);
2012 /* SEEK value = jump to offset,
2013 * from there jump to the end of record,
2014 * go back by (j-1) arguments
2016 MSFT_ReadLEDWords( ¶minfo
,
2017 sizeof(MSFT_ParameterInfo
), pcx
,
2018 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2019 * sizeof(MSFT_ParameterInfo
)));
2023 /* scode is not used: archaic win16 stuff FIXME: right? */
2024 (*pptfd
)->funcdesc
.cScodes
= 0 ;
2025 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
2028 pptfd
= & ((*pptfd
)->next
);
2029 recoffset
+= reclength
;
2031 HeapFree(GetProcessHeap(), 0, recbuf
);
2034 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2035 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2037 int infolen
, nameoffset
, reclength
;
2039 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
2043 TRACE_(typelib
)("\n");
2045 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2046 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2047 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2048 recoffset
+= offset
+sizeof(INT
);
2049 for(i
=0;i
<cVars
;i
++){
2050 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
2051 /* name, eventually add to a hash table */
2052 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2053 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2054 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
2055 /* read the variable information record */
2056 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
2058 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
2060 if(reclength
>(6*sizeof(INT
)) )
2061 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
2062 if(reclength
>(7*sizeof(INT
)) )
2063 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
2064 if(reclength
>(8*sizeof(INT
)) )
2065 if(reclength
>(9*sizeof(INT
)) )
2066 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
2067 /* fill the VarDesc Structure */
2068 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
2069 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2070 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
2071 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
2072 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2073 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
2074 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2075 if(pVarRec
->VarKind
== VAR_CONST
){
2076 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
2077 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
2078 pVarRec
->OffsValue
, pcx
);
2080 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2081 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptvd
)->vardesc
.elemdescVar
.tdesc
);
2082 pptvd
=&((*pptvd
)->next
);
2083 recoffset
+= reclength
;
2086 /* fill in data for a hreftype (offset). When the referenced type is contained
2087 * in the typelib, it's just an (file) offset in the type info base dir.
2088 * If comes from import, it's an offset+1 in the ImpInfo table
2090 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
,
2095 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2097 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
2099 if(ref
->reference
== offset
) return;
2102 ref
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref
));
2103 list_add_tail(&pTL
->ref_list
, &ref
->entry
);
2105 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2106 /* external typelib */
2107 MSFT_ImpInfo impinfo
;
2108 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
2110 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2112 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2113 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2114 while (pImpLib
){ /* search the known offsets of all import libraries */
2115 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
2116 pImpLib
=pImpLib
->next
;
2119 ref
->reference
= offset
;
2120 ref
->pImpTLInfo
= pImpLib
;
2121 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2122 MSFT_ReadGuid(&ref
->guid
, impinfo
.oGuid
, pcx
);
2123 TRACE("importing by guid %s\n", debugstr_guid(&ref
->guid
));
2124 ref
->index
= TLB_REF_USE_GUID
;
2126 ref
->index
= impinfo
.oGuid
;
2128 ERR("Cannot find a reference\n");
2129 ref
->reference
= -1;
2130 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2133 /* in this typelib */
2134 ref
->index
= MSFT_HREFTYPE_INDEX(offset
);
2135 ref
->reference
= offset
;
2136 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
2140 /* process Implemented Interfaces of a com class */
2141 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2145 MSFT_RefRecord refrec
;
2146 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
2148 TRACE_(typelib
)("\n");
2150 for(i
=0;i
<count
;i
++){
2151 if(offset
<0) break; /* paranoia */
2152 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
2153 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2154 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, refrec
.reftype
);
2155 (*ppImpl
)->hRef
= refrec
.reftype
;
2156 (*ppImpl
)->implflags
=refrec
.flags
;
2157 (*ppImpl
)->ctCustData
=
2158 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
2159 offset
=refrec
.onext
;
2160 ppImpl
=&((*ppImpl
)->next
);
2164 * process a typeinfo record
2166 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2169 ITypeLibImpl
* pLibInfo
)
2171 MSFT_TypeInfoBase tiBase
;
2172 ITypeInfoImpl
*ptiRet
;
2174 TRACE_(typelib
)("count=%u\n", count
);
2176 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
2177 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2178 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2180 /* this is where we are coming from */
2181 ptiRet
->pTypeLib
= pLibInfo
;
2182 ptiRet
->index
=count
;
2183 /* fill in the typeattr fields */
2185 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2186 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2187 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2188 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2189 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2190 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2191 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2192 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2193 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2194 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2195 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2196 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2197 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2198 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2199 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2200 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2203 /* IDLDESC idldescType; *//* never saw this one != zero */
2205 /* name, eventually add to a hash table */
2206 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2207 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2208 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2210 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2211 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2212 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2214 if (ptiRet
->TypeAttr
.typekind
== TKIND_MODULE
)
2215 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2217 /* note: InfoType's Help file and HelpStringDll come from the containing
2218 * library. Further HelpString and Docstring appear to be the same thing :(
2221 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2222 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2223 ptiRet
->TypeAttr
.cVars
,
2224 tiBase
.memoffset
, & ptiRet
->funclist
);
2226 if(ptiRet
->TypeAttr
.cVars
>0 )
2227 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2228 ptiRet
->TypeAttr
.cVars
,
2229 tiBase
.memoffset
, & ptiRet
->varlist
);
2230 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2231 switch(ptiRet
->TypeAttr
.typekind
)
2234 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2237 case TKIND_DISPATCH
:
2238 /* This is not -1 when the interface is a non-base dual interface or
2239 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2240 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2244 if (tiBase
.datatype1
!= -1)
2246 ptiRet
->impltypelist
= TLB_Alloc(sizeof(TLBImplType
));
2247 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2248 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2252 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2253 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2254 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2259 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2261 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2262 debugstr_w(ptiRet
->Name
),
2263 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2264 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2265 if (TRACE_ON(typelib
))
2266 dump_TypeInfo(ptiRet
);
2271 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2272 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2273 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2276 static ITypeLibImpl
*tlb_cache_first
;
2277 static CRITICAL_SECTION cache_section
;
2278 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2280 0, 0, &cache_section
,
2281 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2282 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2284 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2287 typedef struct TLB_PEFile
2289 const IUnknownVtbl
*lpvtbl
;
2292 HRSRC typelib_resource
;
2293 HGLOBAL typelib_global
;
2294 LPVOID typelib_base
;
2297 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2299 if (IsEqualIID(riid
, &IID_IUnknown
))
2302 IUnknown_AddRef(iface
);
2306 return E_NOINTERFACE
;
2309 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2311 TLB_PEFile
*This
= (TLB_PEFile
*)iface
;
2312 return InterlockedIncrement(&This
->refs
);
2315 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2317 TLB_PEFile
*This
= (TLB_PEFile
*)iface
;
2318 ULONG refs
= InterlockedDecrement(&This
->refs
);
2321 if (This
->typelib_global
)
2322 FreeResource(This
->typelib_global
);
2324 FreeLibrary(This
->dll
);
2325 HeapFree(GetProcessHeap(), 0, This
);
2330 static const IUnknownVtbl TLB_PEFile_Vtable
=
2332 TLB_PEFile_QueryInterface
,
2337 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2341 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2343 return E_OUTOFMEMORY
;
2345 This
->lpvtbl
= &TLB_PEFile_Vtable
;
2348 This
->typelib_resource
= NULL
;
2349 This
->typelib_global
= NULL
;
2350 This
->typelib_base
= NULL
;
2352 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2353 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2357 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2358 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2359 if (This
->typelib_resource
)
2361 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2362 if (This
->typelib_global
)
2364 This
->typelib_base
= LockResource(This
->typelib_global
);
2366 if (This
->typelib_base
)
2368 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2369 *ppBase
= This
->typelib_base
;
2370 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2377 TLB_PEFile_Release((IUnknown
*)&This
->lpvtbl
);
2378 return TYPE_E_CANTLOADLIBRARY
;
2381 typedef struct TLB_NEFile
2383 const IUnknownVtbl
*lpvtbl
;
2385 LPVOID typelib_base
;
2388 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2390 if (IsEqualIID(riid
, &IID_IUnknown
))
2393 IUnknown_AddRef(iface
);
2397 return E_NOINTERFACE
;
2400 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2402 TLB_NEFile
*This
= (TLB_NEFile
*)iface
;
2403 return InterlockedIncrement(&This
->refs
);
2406 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2408 TLB_NEFile
*This
= (TLB_NEFile
*)iface
;
2409 ULONG refs
= InterlockedDecrement(&This
->refs
);
2412 HeapFree(GetProcessHeap(), 0, This
->typelib_base
);
2413 HeapFree(GetProcessHeap(), 0, This
);
2418 static const IUnknownVtbl TLB_NEFile_Vtable
=
2420 TLB_NEFile_QueryInterface
,
2425 /***********************************************************************
2426 * read_xx_header [internal]
2428 static int read_xx_header( HFILE lzfd
)
2430 IMAGE_DOS_HEADER mzh
;
2433 LZSeek( lzfd
, 0, SEEK_SET
);
2434 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
2436 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
2439 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2440 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
2443 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2445 if ( magic
[0] == 'N' && magic
[1] == 'E' )
2446 return IMAGE_OS2_SIGNATURE
;
2447 if ( magic
[0] == 'P' && magic
[1] == 'E' )
2448 return IMAGE_NT_SIGNATURE
;
2451 WARN("Can't handle %s files.\n", magic
);
2456 /***********************************************************************
2457 * find_ne_resource [internal]
2459 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
2460 DWORD
*resLen
, DWORD
*resOff
)
2462 IMAGE_OS2_HEADER nehd
;
2463 NE_TYPEINFO
*typeInfo
;
2464 NE_NAMEINFO
*nameInfo
;
2470 /* Read in NE header */
2471 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
2472 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
2474 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
2477 TRACE("No resources in NE dll\n" );
2481 /* Read in resource table */
2482 resTab
= HeapAlloc( GetProcessHeap(), 0, resTabSize
);
2483 if ( !resTab
) return FALSE
;
2485 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
2486 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
2488 HeapFree( GetProcessHeap(), 0, resTab
);
2493 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
2495 if (HIWORD(typeid) != 0) /* named type */
2497 BYTE len
= strlen( typeid );
2498 while (typeInfo
->type_id
)
2500 if (!(typeInfo
->type_id
& 0x8000))
2502 BYTE
*p
= resTab
+ typeInfo
->type_id
;
2503 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
2505 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2506 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2509 else /* numeric type id */
2511 WORD id
= LOWORD(typeid) | 0x8000;
2512 while (typeInfo
->type_id
)
2514 if (typeInfo
->type_id
== id
) goto found_type
;
2515 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2516 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2519 TRACE("No typeid entry found for %p\n", typeid );
2520 HeapFree( GetProcessHeap(), 0, resTab
);
2524 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
2526 if (HIWORD(resid
) != 0) /* named resource */
2528 BYTE len
= strlen( resid
);
2529 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2531 BYTE
*p
= resTab
+ nameInfo
->id
;
2532 if (nameInfo
->id
& 0x8000) continue;
2533 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
2536 else /* numeric resource id */
2538 WORD id
= LOWORD(resid
) | 0x8000;
2539 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2540 if (nameInfo
->id
== id
) goto found_name
;
2542 TRACE("No resid entry found for %p\n", typeid );
2543 HeapFree( GetProcessHeap(), 0, resTab
);
2547 /* Return resource data */
2548 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
2549 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
2551 HeapFree( GetProcessHeap(), 0, resTab
);
2555 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
2559 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2560 TLB_NEFile
*This
= NULL
;
2562 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2563 if (!This
) return E_OUTOFMEMORY
;
2565 This
->lpvtbl
= &TLB_NEFile_Vtable
;
2567 This
->typelib_base
= NULL
;
2569 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
2570 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
2572 DWORD reslen
, offset
;
2573 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
2575 This
->typelib_base
= HeapAlloc(GetProcessHeap(), 0, reslen
);
2576 if( !This
->typelib_base
)
2580 LZSeek( lzfd
, offset
, SEEK_SET
);
2581 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
2583 *ppBase
= This
->typelib_base
;
2584 *pdwTLBLength
= reslen
;
2585 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2591 if( lzfd
>= 0) LZClose( lzfd
);
2592 TLB_NEFile_Release((IUnknown
*)&This
->lpvtbl
);
2596 typedef struct TLB_Mapping
2598 const IUnknownVtbl
*lpvtbl
;
2602 LPVOID typelib_base
;
2605 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2607 if (IsEqualIID(riid
, &IID_IUnknown
))
2610 IUnknown_AddRef(iface
);
2614 return E_NOINTERFACE
;
2617 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
2619 TLB_Mapping
*This
= (TLB_Mapping
*)iface
;
2620 return InterlockedIncrement(&This
->refs
);
2623 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
2625 TLB_Mapping
*This
= (TLB_Mapping
*)iface
;
2626 ULONG refs
= InterlockedDecrement(&This
->refs
);
2629 if (This
->typelib_base
)
2630 UnmapViewOfFile(This
->typelib_base
);
2632 CloseHandle(This
->mapping
);
2633 if (This
->file
!= INVALID_HANDLE_VALUE
)
2634 CloseHandle(This
->file
);
2635 HeapFree(GetProcessHeap(), 0, This
);
2640 static const IUnknownVtbl TLB_Mapping_Vtable
=
2642 TLB_Mapping_QueryInterface
,
2647 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2651 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2653 return E_OUTOFMEMORY
;
2655 This
->lpvtbl
= &TLB_Mapping_Vtable
;
2657 This
->file
= INVALID_HANDLE_VALUE
;
2658 This
->mapping
= NULL
;
2659 This
->typelib_base
= NULL
;
2661 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
2662 if (INVALID_HANDLE_VALUE
!= This
->file
)
2664 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2667 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
2668 if(This
->typelib_base
)
2670 /* retrieve file size */
2671 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
2672 *ppBase
= This
->typelib_base
;
2673 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2679 IUnknown_Release((IUnknown
*)&This
->lpvtbl
);
2680 return TYPE_E_CANTLOADLIBRARY
;
2683 /****************************************************************************
2686 * find the type of the typelib file and map the typelib resource into
2689 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2690 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2691 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
2693 ITypeLibImpl
*entry
;
2696 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
2697 LPVOID pBase
= NULL
;
2698 DWORD dwTLBLength
= 0;
2699 IUnknown
*pFile
= NULL
;
2703 index_str
= strrchrW(pszFileName
, '\\');
2704 if(index_str
&& *++index_str
!= '\0')
2707 long idx
= strtolW(index_str
, &end_ptr
, 10);
2708 if(*end_ptr
== '\0')
2710 int str_len
= index_str
- pszFileName
- 1;
2712 file
= HeapAlloc(GetProcessHeap(), 0, (str_len
+ 1) * sizeof(WCHAR
));
2713 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
2718 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
2720 if(strchrW(file
, '\\'))
2722 lstrcpyW(pszPath
, file
);
2726 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
2727 pszPath
[len
] = '\\';
2728 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
2732 if(file
!= pszFileName
) HeapFree(GetProcessHeap(), 0, file
);
2734 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
2736 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2737 EnterCriticalSection(&cache_section
);
2738 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2740 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
2742 TRACE("cache hit\n");
2743 *ppTypeLib
= (ITypeLib2
*)entry
;
2744 ITypeLib_AddRef(*ppTypeLib
);
2745 LeaveCriticalSection(&cache_section
);
2749 LeaveCriticalSection(&cache_section
);
2751 /* now actually load and parse the typelib */
2753 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2754 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2755 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2756 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2757 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
2760 if (dwTLBLength
>= 4)
2762 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2763 if (dwSignature
== MSFT_SIGNATURE
)
2764 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2765 else if (dwSignature
== SLTG_SIGNATURE
)
2766 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2769 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
2770 ret
= TYPE_E_CANTLOADLIBRARY
;
2774 ret
= TYPE_E_CANTLOADLIBRARY
;
2775 IUnknown_Release(pFile
);
2779 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2781 TRACE("adding to cache\n");
2782 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath
)+1) * sizeof(WCHAR
));
2783 lstrcpyW(impl
->path
, pszPath
);
2784 /* We should really canonicalise the path here. */
2785 impl
->index
= index
;
2787 /* FIXME: check if it has added already in the meantime */
2788 EnterCriticalSection(&cache_section
);
2789 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2791 tlb_cache_first
= impl
;
2792 LeaveCriticalSection(&cache_section
);
2795 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
2800 /*================== ITypeLib(2) Methods ===================================*/
2802 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
2804 ITypeLibImpl
* pTypeLibImpl
;
2806 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2807 if (!pTypeLibImpl
) return NULL
;
2809 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2810 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2811 pTypeLibImpl
->ref
= 1;
2813 list_init(&pTypeLibImpl
->ref_list
);
2814 pTypeLibImpl
->dispatch_href
= -1;
2816 return pTypeLibImpl
;
2819 /****************************************************************************
2820 * ITypeLib2_Constructor_MSFT
2822 * loading an MSFT typelib from an in-memory image
2824 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2828 MSFT_Header tlbHeader
;
2829 MSFT_SegDir tlbSegDir
;
2830 ITypeLibImpl
* pTypeLibImpl
;
2832 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
2834 pTypeLibImpl
= TypeLibImpl_Constructor();
2835 if (!pTypeLibImpl
) return NULL
;
2837 /* get pointer to beginning of typelib data */
2841 cx
.pLibInfo
= pTypeLibImpl
;
2842 cx
.length
= dwTLBLength
;
2845 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2846 TRACE_(typelib
)("header:\n");
2847 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2848 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2849 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2852 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
2854 /* there is a small amount of information here until the next important
2856 * the segment directory . Try to calculate the amount of data */
2857 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2859 /* now read the segment directory */
2860 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2861 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2862 cx
.pTblDir
= &tlbSegDir
;
2864 /* just check two entries */
2865 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2867 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2868 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2872 /* now fill our internal data */
2873 /* TLIBATTR fields */
2874 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2876 pTypeLibImpl
->LibAttr
.lcid
= tlbHeader
.lcid2
;
2877 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2878 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2879 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2880 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2882 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
2884 /* name, eventually add to a hash table */
2885 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2888 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2889 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2891 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2894 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2895 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2898 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2901 if(tlbHeader
.CustomDataOffset
>= 0)
2903 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2906 /* fill in type descriptions */
2907 if(tlbSegDir
.pTypdescTab
.length
> 0)
2909 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2911 pTypeLibImpl
->ctTypeDesc
= cTD
;
2912 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2913 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2916 /* FIXME: add several sanity checks here */
2917 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2918 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2920 /* FIXME: check safearray */
2922 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2924 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2926 else if(td
[0] == VT_CARRAY
)
2928 /* array descr table here */
2929 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2931 else if(td
[0] == VT_USERDEFINED
)
2933 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2935 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2938 /* second time around to fill the array subscript info */
2941 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2942 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2944 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2945 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2948 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2950 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
2952 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2954 for(j
= 0; j
<td
[2]; j
++)
2956 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2957 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2958 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2959 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2964 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2965 ERR("didn't find array description data\n");
2970 /* imported type libs */
2971 if(tlbSegDir
.pImpFiles
.offset
>0)
2973 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2974 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2977 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2981 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2982 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2983 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2985 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2986 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2987 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2988 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2991 name
= TLB_Alloc(size
+1);
2992 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2993 (*ppImpLib
)->name
= TLB_MultiByteToBSTR(name
);
2995 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2996 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2998 ppImpLib
= &(*ppImpLib
)->next
;
3002 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3003 if(pTypeLibImpl
->dispatch_href
!= -1)
3004 MSFT_DoRefType(&cx
, pTypeLibImpl
, pTypeLibImpl
->dispatch_href
);
3007 if(tlbHeader
.nrtypeinfos
>= 0 )
3009 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3010 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
3013 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3015 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3017 ppTI
= &((*ppTI
)->next
);
3018 (pTypeLibImpl
->TypeInfoCount
)++;
3022 TRACE("(%p)\n", pTypeLibImpl
);
3023 return (ITypeLib2
*) pTypeLibImpl
;
3027 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3033 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3034 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3038 guid
->Data4
[0] = s
>> 8;
3039 guid
->Data4
[1] = s
& 0xff;
3042 for(i
= 0; i
< 6; i
++) {
3043 memcpy(b
, str
+ 24 + 2 * i
, 2);
3044 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3049 static WORD
SLTG_ReadString(const char *ptr
, BSTR
*pBstr
)
3055 bytelen
= *(const WORD
*)ptr
;
3056 if(bytelen
== 0xffff) return 2;
3057 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3058 *pBstr
= SysAllocStringLen(NULL
, len
);
3060 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, *pBstr
, len
);
3064 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3069 bytelen
= *(const WORD
*)ptr
;
3070 if(bytelen
== 0xffff) return 2;
3071 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
3072 memcpy(*str
, ptr
+ 2, bytelen
);
3073 (*str
)[bytelen
] = '\0';
3077 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3079 char *ptr
= pLibBlk
;
3082 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3083 FIXME("libblk magic = %04x\n", w
);
3088 if((w
= *(WORD
*)ptr
) != 0xffff) {
3089 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3094 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
3096 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
3098 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3101 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
3104 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3105 pTypeLibImpl
->lcid
= pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3107 pTypeLibImpl
->lcid
= pTypeLibImpl
->LibAttr
.lcid
= 0;
3110 ptr
+= 4; /* skip res12 */
3112 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
3115 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
3118 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
3121 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
3122 ptr
+= sizeof(GUID
);
3124 return ptr
- (char*)pLibBlk
;
3127 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3132 } sltg_ref_lookup_t
;
3134 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3135 HREFTYPE
*typelib_ref
)
3137 if(table
&& typeinfo_ref
< table
->num
)
3139 *typelib_ref
= table
->refs
[typeinfo_ref
];
3143 ERR_(typelib
)("Unable to find reference\n");
3148 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3153 if((*pType
& 0xe00) == 0xe00) {
3155 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3157 pTD
= pTD
->u
.lptdesc
;
3159 switch(*pType
& 0x3f) {
3162 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3164 pTD
= pTD
->u
.lptdesc
;
3167 case VT_USERDEFINED
:
3168 pTD
->vt
= VT_USERDEFINED
;
3169 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3175 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3178 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3180 pTD
->vt
= VT_CARRAY
;
3181 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3183 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3184 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3185 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3186 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3188 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3194 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3198 pTD
->vt
= VT_SAFEARRAY
;
3199 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3201 pTD
= pTD
->u
.lptdesc
;
3205 pTD
->vt
= *pType
& 0x3f;
3214 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3215 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3217 /* Handle [in/out] first */
3218 if((*pType
& 0xc000) == 0xc000)
3219 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3220 else if(*pType
& 0x8000)
3221 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3222 else if(*pType
& 0x4000)
3223 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3225 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3228 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3231 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3233 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3237 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3242 TLBRefType
*ref_type
;
3243 sltg_ref_lookup_t
*table
;
3244 HREFTYPE typelib_ref
;
3246 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3247 FIXME("Ref magic = %x\n", pRef
->magic
);
3250 name
= ( (char*)pRef
->names
+ pRef
->number
);
3252 table
= HeapAlloc(GetProcessHeap(), 0, sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3253 table
->num
= pRef
->number
>> 3;
3255 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3257 /* We don't want the first href to be 0 */
3258 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3260 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3262 unsigned int lib_offs
, type_num
;
3264 ref_type
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref_type
));
3266 name
+= SLTG_ReadStringA(name
, &refname
);
3267 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3268 FIXME_(typelib
)("Can't sscanf ref\n");
3269 if(lib_offs
!= 0xffff) {
3270 TLBImpLib
**import
= &pTL
->pImpLibs
;
3273 if((*import
)->offset
== lib_offs
)
3275 import
= &(*import
)->next
;
3278 char fname
[MAX_PATH
+1];
3281 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3283 (*import
)->offset
= lib_offs
;
3284 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
3286 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3287 &(*import
)->wVersionMajor
,
3288 &(*import
)->wVersionMinor
,
3289 &(*import
)->lcid
, fname
) != 4) {
3290 FIXME_(typelib
)("can't sscanf ref %s\n",
3291 pNameTable
+ lib_offs
+ 40);
3293 len
= strlen(fname
);
3294 if(fname
[len
-1] != '#')
3295 FIXME("fname = %s\n", fname
);
3296 fname
[len
-1] = '\0';
3297 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
3299 ref_type
->pImpTLInfo
= *import
;
3301 /* Store a reference to IDispatch */
3302 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&(*import
)->guid
, &IID_StdOle
) && type_num
== 4)
3303 pTL
->dispatch_href
= typelib_ref
;
3305 } else { /* internal ref */
3306 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3308 ref_type
->reference
= typelib_ref
;
3309 ref_type
->index
= type_num
;
3311 HeapFree(GetProcessHeap(), 0, refname
);
3312 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3314 table
->refs
[ref
] = typelib_ref
;
3317 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3318 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3319 dump_TLBRefType(pTL
);
3323 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3324 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3326 SLTG_ImplInfo
*info
;
3327 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
3328 /* I don't really get this structure, usually it's 0x16 bytes
3329 long, but iuser.tlb contains some that are 0x18 bytes long.
3330 That's ok because we can use the next ptr to jump to the next
3331 one. But how do we know the length of the last one? The WORD
3332 at offs 0x8 might be the clue. For now I'm just assuming that
3333 the last one is the regular 0x16 bytes. */
3335 info
= (SLTG_ImplInfo
*)pBlk
;
3337 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3338 sizeof(**ppImplType
));
3339 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &(*ppImplType
)->hRef
);
3340 (*ppImplType
)->implflags
= info
->impltypeflags
;
3341 pTI
->TypeAttr
.cImplTypes
++;
3342 ppImplType
= &(*ppImplType
)->next
;
3344 if(info
->next
== 0xffff)
3347 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3348 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3350 info
++; /* see comment at top of function */
3354 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
3355 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3357 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
3358 BSTR bstrPrevName
= NULL
;
3359 SLTG_Variable
*pItem
;
3363 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
3364 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++) {
3366 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3367 sizeof(**ppVarDesc
));
3368 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
3370 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
3371 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
3372 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
3376 if (pItem
->name
== 0xfffe)
3377 (*ppVarDesc
)->Name
= SysAllocString(bstrPrevName
);
3379 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3381 TRACE_(typelib
)("name: %s\n", debugstr_w((*ppVarDesc
)->Name
));
3382 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
3383 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
3385 if(pItem
->flags
& 0x02)
3386 pType
= &pItem
->type
;
3388 pType
= (WORD
*)(pBlk
+ pItem
->type
);
3390 if (pItem
->flags
& ~0xda)
3391 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
3393 SLTG_DoElem(pType
, pBlk
,
3394 &(*ppVarDesc
)->vardesc
.elemdescVar
, ref_lookup
);
3396 if (TRACE_ON(typelib
)) {
3398 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
3399 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
3402 if (pItem
->flags
& 0x40) {
3403 TRACE_(typelib
)("VAR_DISPATCH\n");
3404 (*ppVarDesc
)->vardesc
.varkind
= VAR_DISPATCH
;
3406 else if (pItem
->flags
& 0x10) {
3407 TRACE_(typelib
)("VAR_CONST\n");
3408 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
3409 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
3411 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
3412 if (pItem
->flags
& 0x08)
3413 V_INT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
3415 switch ((*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
)
3421 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
3423 TRACE_(typelib
)("len = %u\n", len
);
3424 if (len
== 0xffff) {
3427 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
3428 str
= SysAllocStringLen(NULL
, alloc_len
);
3429 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
3431 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_BSTR
;
3432 V_BSTR((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = str
;
3441 V_INT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) =
3442 *(INT
*)(pBlk
+ pItem
->byte_offs
);
3445 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
);
3450 TRACE_(typelib
)("VAR_PERINSTANCE\n");
3451 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
3452 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
3455 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
3456 (*ppVarDesc
)->vardesc
.wVarFlags
= pItem
->varflags
;
3458 if (pItem
->flags
& 0x80)
3459 (*ppVarDesc
)->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
3461 bstrPrevName
= (*ppVarDesc
)->Name
;
3462 ppVarDesc
= &((*ppVarDesc
)->next
);
3464 pTI
->TypeAttr
.cVars
= cVars
;
3467 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
3468 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3470 SLTG_Function
*pFunc
;
3472 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
3474 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
;
3475 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++) {
3480 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3481 sizeof(**ppFuncDesc
));
3483 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
3484 case SLTG_FUNCTION_MAGIC
:
3485 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
3487 case SLTG_DISPATCH_FUNCTION_MAGIC
:
3488 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_DISPATCH
;
3490 case SLTG_STATIC_FUNCTION_MAGIC
:
3491 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_STATIC
;
3494 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
3495 HeapFree(GetProcessHeap(), 0, *ppFuncDesc
);
3499 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
3501 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
3502 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
3503 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
3504 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
3505 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
3506 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
3508 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
3509 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
3511 if(pFunc
->retnextopt
& 0x80)
3512 pType
= &pFunc
->rettype
;
3514 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
3516 SLTG_DoElem(pType
, pBlk
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
, ref_lookup
);
3518 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
3519 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3520 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
3521 (*ppFuncDesc
)->pParamDesc
=
3522 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3523 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
3525 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
3527 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
3528 char *paramName
= pNameTable
+ *pArg
;
3530 /* If arg type follows then paramName points to the 2nd
3531 letter of the name, else the next WORD is an offset to
3532 the arg type and paramName points to the first letter.
3533 So let's take one char off paramName and see if we're
3534 pointing at an alpha-numeric char. However if *pArg is
3535 0xffff or 0xfffe then the param has no name, the former
3536 meaning that the next WORD is the type, the latter
3537 meaning that the next WORD is an offset to the type. */
3542 else if(*pArg
== 0xfffe) {
3546 else if(paramName
[-1] && !isalnum(paramName
[-1]))
3551 if(HaveOffs
) { /* the next word is an offset to type */
3552 pType
= (WORD
*)(pBlk
+ *pArg
);
3553 SLTG_DoElem(pType
, pBlk
,
3554 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3559 pArg
= SLTG_DoElem(pArg
, pBlk
,
3560 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3563 /* Are we an optional param ? */
3564 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
3565 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
3566 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
3569 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
3570 TLB_MultiByteToBSTR(paramName
);
3572 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
3573 SysAllocString((*ppFuncDesc
)->Name
);
3577 ppFuncDesc
= &((*ppFuncDesc
)->next
);
3578 if(pFunc
->next
== 0xffff) break;
3580 pTI
->TypeAttr
.cFuncs
= cFuncs
;
3583 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
3584 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3585 SLTG_TypeInfoTail
*pTITail
)
3588 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3590 if(pTIHeader
->href_table
!= 0xffffffff) {
3591 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3597 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3598 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
3600 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3604 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
3605 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3606 const SLTG_TypeInfoTail
*pTITail
)
3609 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3611 if(pTIHeader
->href_table
!= 0xffffffff) {
3612 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3618 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3619 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
3622 if (pTITail
->funcs_off
!= 0xffff)
3623 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3625 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3627 if (TRACE_ON(typelib
))
3628 dump_TLBFuncDesc(pTI
->funclist
);
3631 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
3632 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3633 const SLTG_TypeInfoTail
*pTITail
)
3635 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3638 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3639 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3640 const SLTG_TypeInfoTail
*pTITail
)
3643 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3645 if (pTITail
->simple_alias
) {
3646 /* if simple alias, no more processing required */
3647 pTI
->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3651 if(pTIHeader
->href_table
!= 0xffffffff) {
3652 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3656 /* otherwise it is an offset to a type */
3657 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
3659 SLTG_DoType(pType
, pBlk
, &pTI
->TypeAttr
.tdescAlias
, ref_lookup
);
3661 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3664 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3665 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3666 const SLTG_TypeInfoTail
*pTITail
)
3668 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3669 if (pTIHeader
->href_table
!= 0xffffffff)
3670 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3673 if (pTITail
->vars_off
!= 0xffff)
3674 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3676 if (pTITail
->funcs_off
!= 0xffff)
3677 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3679 if (pTITail
->impls_off
!= 0xffff)
3680 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
3682 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3683 * of dispinterface functions including the IDispatch ones, so
3684 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3685 pTI
->TypeAttr
.cbSizeVft
= pTI
->TypeAttr
.cFuncs
* sizeof(void *);
3687 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3688 if (TRACE_ON(typelib
))
3689 dump_TLBFuncDesc(pTI
->funclist
);
3692 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3693 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3694 const SLTG_TypeInfoTail
*pTITail
)
3696 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3699 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
3700 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3701 const SLTG_TypeInfoTail
*pTITail
)
3703 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3704 if (pTIHeader
->href_table
!= 0xffffffff)
3705 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3708 if (pTITail
->vars_off
!= 0xffff)
3709 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3711 if (pTITail
->funcs_off
!= 0xffff)
3712 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3713 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3714 if (TRACE_ON(typelib
))
3718 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3719 managable copy of it into this */
3732 } SLTG_InternalOtherTypeInfo
;
3734 /****************************************************************************
3735 * ITypeLib2_Constructor_SLTG
3737 * loading a SLTG typelib from an in-memory image
3739 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3741 ITypeLibImpl
*pTypeLibImpl
;
3742 SLTG_Header
*pHeader
;
3743 SLTG_BlkEntry
*pBlkEntry
;
3747 LPVOID pBlk
, pFirstBlk
;
3748 SLTG_LibBlk
*pLibBlk
;
3749 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3750 char *pAfterOTIBlks
= NULL
;
3751 char *pNameTable
, *ptr
;
3754 ITypeInfoImpl
**ppTypeInfoImpl
;
3756 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3759 pTypeLibImpl
= TypeLibImpl_Constructor();
3760 if (!pTypeLibImpl
) return NULL
;
3764 TRACE_(typelib
)("header:\n");
3765 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
3766 pHeader
->nrOfFileBlks
);
3767 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3768 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
3769 pHeader
->SLTG_magic
);
3773 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3774 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3776 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3777 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3779 /* Next we have a magic block */
3780 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3782 /* Let's see if we're still in sync */
3783 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3784 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3785 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3788 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3789 sizeof(SLTG_DIR_MAGIC
))) {
3790 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
3794 pIndex
= (SLTG_Index
*)(pMagic
+1);
3796 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3798 pFirstBlk
= pPad9
+ 1;
3800 /* We'll set up a ptr to the main library block, which is the last one. */
3802 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3803 pBlkEntry
[order
].next
!= 0;
3804 order
= pBlkEntry
[order
].next
- 1, i
++) {
3805 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3809 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3811 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3816 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3818 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3819 sizeof(*pOtherTypeInfoBlks
) *
3820 pTypeLibImpl
->TypeInfoCount
);
3823 ptr
= (char*)pLibBlk
+ len
;
3825 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3829 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3831 w
= *(WORD
*)(ptr
+ 2);
3834 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3836 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3837 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3839 w
= *(WORD
*)(ptr
+ 4 + len
);
3841 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3843 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3845 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3846 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3848 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3849 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3850 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3852 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3854 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3857 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3858 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3859 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3860 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3861 len
+= sizeof(SLTG_OtherTypeInfo
);
3865 pAfterOTIBlks
= ptr
;
3867 /* Skip this WORD and get the next DWORD */
3868 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3870 /* Now add this to pLibBLk look at what we're pointing at and
3871 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3872 dust and we should be pointing at the beginning of the name
3875 pNameTable
= (char*)pLibBlk
+ len
;
3877 switch(*(WORD
*)pNameTable
) {
3884 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3888 pNameTable
+= 0x216;
3892 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3894 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3897 /* Hopefully we now have enough ptrs set up to actually read in
3898 some TypeInfos. It's not clear which order to do them in, so
3899 I'll just follow the links along the BlkEntry chain and read
3900 them in the order in which they are in the file */
3902 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3904 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3905 pBlkEntry
[order
].next
!= 0;
3906 order
= pBlkEntry
[order
].next
- 1, i
++) {
3908 SLTG_TypeInfoHeader
*pTIHeader
;
3909 SLTG_TypeInfoTail
*pTITail
;
3910 SLTG_MemberHeader
*pMemHeader
;
3912 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3913 pOtherTypeInfoBlks
[i
].index_name
)) {
3914 FIXME_(typelib
)("Index strings don't match\n");
3919 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3920 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3923 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3924 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3925 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
3927 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3928 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3929 (*ppTypeInfoImpl
)->index
= i
;
3930 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3931 pOtherTypeInfoBlks
[i
].name_offs
+
3933 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3934 (*ppTypeInfoImpl
)->TypeAttr
.guid
= pOtherTypeInfoBlks
[i
].uuid
;
3935 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3936 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3937 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3938 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3939 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3941 if((*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
3942 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= TKIND_DISPATCH
;
3944 if((pTIHeader
->typeflags1
& 7) != 2)
3945 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3946 if(pTIHeader
->typeflags3
!= 2)
3947 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3949 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3950 debugstr_w((*ppTypeInfoImpl
)->Name
),
3951 typekind_desc
[pTIHeader
->typekind
],
3952 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3953 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3955 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
3957 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
3959 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3960 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3961 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3963 switch(pTIHeader
->typekind
) {
3965 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3966 pTIHeader
, pTITail
);
3970 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3971 pTIHeader
, pTITail
);
3974 case TKIND_INTERFACE
:
3975 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3976 pTIHeader
, pTITail
);
3980 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3981 pTIHeader
, pTITail
);
3985 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3986 pTIHeader
, pTITail
);
3989 case TKIND_DISPATCH
:
3990 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3991 pTIHeader
, pTITail
);
3995 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3996 pTIHeader
, pTITail
);
4000 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4005 /* could get cFuncs, cVars and cImplTypes from here
4006 but we've already set those */
4007 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4022 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
4023 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4026 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4027 FIXME("Somehow processed %d TypeInfos\n", i
);
4031 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
4032 return (ITypeLib2
*)pTypeLibImpl
;
4035 /* ITypeLib::QueryInterface
4037 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
4042 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4044 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4047 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4048 IsEqualIID(riid
,&IID_ITypeLib
)||
4049 IsEqualIID(riid
,&IID_ITypeLib2
))
4056 ITypeLib2_AddRef(iface
);
4057 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4060 TRACE("-- Interface: E_NOINTERFACE\n");
4061 return E_NOINTERFACE
;
4066 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4068 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4069 ULONG ref
= InterlockedIncrement(&This
->ref
);
4071 TRACE("(%p)->ref was %u\n",This
, ref
- 1);
4076 /* ITypeLib::Release
4078 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4080 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4081 ULONG ref
= InterlockedDecrement(&This
->ref
);
4083 TRACE("(%p)->(%u)\n",This
, ref
);
4087 TLBImpLib
*pImpLib
, *pImpLibNext
;
4088 TLBCustData
*pCustData
, *pCustDataNext
;
4089 TLBRefType
*ref_type
;
4093 /* remove cache entry */
4096 TRACE("removing from cache list\n");
4097 EnterCriticalSection(&cache_section
);
4098 if (This
->next
) This
->next
->prev
= This
->prev
;
4099 if (This
->prev
) This
->prev
->next
= This
->next
;
4100 else tlb_cache_first
= This
->next
;
4101 LeaveCriticalSection(&cache_section
);
4102 HeapFree(GetProcessHeap(), 0, This
->path
);
4104 TRACE(" destroying ITypeLib(%p)\n",This
);
4106 SysFreeString(This
->Name
);
4109 SysFreeString(This
->DocString
);
4110 This
->DocString
= NULL
;
4112 SysFreeString(This
->HelpFile
);
4113 This
->HelpFile
= NULL
;
4115 SysFreeString(This
->HelpStringDll
);
4116 This
->HelpStringDll
= NULL
;
4118 for (pCustData
= This
->pCustData
; pCustData
; pCustData
= pCustDataNext
)
4120 VariantClear(&pCustData
->data
);
4122 pCustDataNext
= pCustData
->next
;
4123 TLB_Free(pCustData
);
4126 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4127 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4128 TLB_Free(This
->pTypeDesc
[i
].u
.lpadesc
);
4130 TLB_Free(This
->pTypeDesc
);
4132 for (pImpLib
= This
->pImpLibs
; pImpLib
; pImpLib
= pImpLibNext
)
4134 if (pImpLib
->pImpTypeLib
)
4135 ITypeLib_Release((ITypeLib
*)pImpLib
->pImpTypeLib
);
4136 SysFreeString(pImpLib
->name
);
4138 pImpLibNext
= pImpLib
->next
;
4142 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4144 list_remove(&ref_type
->entry
);
4148 if (This
->pTypeInfo
) /* can be NULL */
4149 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
4150 HeapFree(GetProcessHeap(),0,This
);
4157 /* ITypeLib::GetTypeInfoCount
4159 * Returns the number of type descriptions in the type library
4161 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4163 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4164 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4165 return This
->TypeInfoCount
;
4168 /* ITypeLib::GetTypeInfo
4170 * retrieves the specified type description in the library.
4172 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4175 ITypeInfo
**ppTInfo
)
4179 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4180 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
4182 TRACE("(%p)->(index=%d)\n", This
, index
);
4184 if (!ppTInfo
) return E_INVALIDARG
;
4186 /* search element n in list */
4187 for(i
=0; i
< index
; i
++)
4189 pTypeInfo
= pTypeInfo
->next
;
4192 TRACE("-- element not found\n");
4193 return TYPE_E_ELEMENTNOTFOUND
;
4197 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
4199 ITypeInfo_AddRef(*ppTInfo
);
4200 TRACE("-- found (%p)\n",*ppTInfo
);
4205 /* ITypeLibs::GetTypeInfoType
4207 * Retrieves the type of a type description.
4209 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4214 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4216 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
4218 if (ITypeLib2_fnGetTypeInfoCount(iface
) < index
+ 1)
4219 return TYPE_E_ELEMENTNOTFOUND
;
4221 TRACE("(%p) index %d\n", This
, index
);
4223 if(!pTKind
) return E_INVALIDARG
;
4225 /* search element n in list */
4226 for(i
=0; i
< index
; i
++)
4230 TRACE("-- element not found\n");
4231 return TYPE_E_ELEMENTNOTFOUND
;
4233 pTInfo
= pTInfo
->next
;
4236 *pTKind
= pTInfo
->TypeAttr
.typekind
;
4237 TRACE("-- found Type (%d)\n", *pTKind
);
4241 /* ITypeLib::GetTypeInfoOfGuid
4243 * Retrieves the type description that corresponds to the specified GUID.
4246 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4249 ITypeInfo
**ppTInfo
)
4251 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4252 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
4254 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
4258 WARN("-- element not found\n");
4259 return TYPE_E_ELEMENTNOTFOUND
;
4262 /* search linked list for guid */
4263 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
4265 pTypeInfo
= pTypeInfo
->next
;
4269 /* end of list reached */
4270 WARN("-- element not found\n");
4271 return TYPE_E_ELEMENTNOTFOUND
;
4275 TRACE("-- found (%p, %s)\n",
4277 debugstr_w(pTypeInfo
->Name
));
4279 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
4280 ITypeInfo_AddRef(*ppTInfo
);
4284 /* ITypeLib::GetLibAttr
4286 * Retrieves the structure that contains the library's attributes.
4289 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4291 LPTLIBATTR
*ppTLibAttr
)
4293 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4294 TRACE("(%p)\n",This
);
4295 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
4296 **ppTLibAttr
= This
->LibAttr
;
4300 /* ITypeLib::GetTypeComp
4302 * Enables a client compiler to bind to a library's types, variables,
4303 * constants, and global functions.
4306 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4308 ITypeComp
**ppTComp
)
4310 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4312 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4313 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4314 ITypeComp_AddRef(*ppTComp
);
4319 /* ITypeLib::GetDocumentation
4321 * Retrieves the library's documentation string, the complete Help file name
4322 * and path, and the context identifier for the library Help topic in the Help
4325 * On a successful return all non-null BSTR pointers will have been set,
4328 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4332 BSTR
*pBstrDocString
,
4333 DWORD
*pdwHelpContext
,
4334 BSTR
*pBstrHelpFile
)
4336 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4338 HRESULT result
= E_INVALIDARG
;
4343 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4345 pBstrName
, pBstrDocString
,
4346 pdwHelpContext
, pBstrHelpFile
);
4350 /* documentation for the typelib */
4355 if(!(*pBstrName
= SysAllocString(This
->Name
)))
4363 if (This
->DocString
)
4365 if(!(*pBstrDocString
= SysAllocString(This
->DocString
)))
4368 else if (This
->Name
)
4370 if(!(*pBstrDocString
= SysAllocString(This
->Name
)))
4374 *pBstrDocString
= NULL
;
4378 *pdwHelpContext
= This
->dwHelpContext
;
4384 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
)))
4388 *pBstrHelpFile
= NULL
;
4395 /* for a typeinfo */
4396 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4398 if(SUCCEEDED(result
))
4400 result
= ITypeInfo_GetDocumentation(pTInfo
,
4404 pdwHelpContext
, pBstrHelpFile
);
4406 ITypeInfo_Release(pTInfo
);
4411 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
4413 if (pBstrName
) SysFreeString (*pBstrName
);
4415 return STG_E_INSUFFICIENTMEMORY
;
4420 * Indicates whether a passed-in string contains the name of a type or member
4421 * described in the library.
4424 static HRESULT WINAPI
ITypeLib2_fnIsName(
4430 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4431 ITypeInfoImpl
*pTInfo
;
4432 TLBFuncDesc
*pFInfo
;
4435 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
4437 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
4441 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
4442 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4443 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
4444 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4445 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
4446 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
4447 goto ITypeLib2_fnIsName_exit
;
4449 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
4450 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4455 ITypeLib2_fnIsName_exit
:
4456 TRACE("(%p)slow! search for %s: %s found!\n", This
,
4457 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
4462 /* ITypeLib::FindName
4464 * Finds occurrences of a type description in a type library. This may be used
4465 * to quickly verify that a name exists in a type library.
4468 static HRESULT WINAPI
ITypeLib2_fnFindName(
4472 ITypeInfo
**ppTInfo
,
4476 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4477 ITypeInfoImpl
*pTInfo
;
4478 TLBFuncDesc
*pFInfo
;
4481 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
4483 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
4484 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4485 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
4486 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4487 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++) {
4488 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
4489 goto ITypeLib2_fnFindName_exit
;
4492 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
4493 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4495 ITypeLib2_fnFindName_exit
:
4496 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
4497 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
4500 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4501 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
4508 /* ITypeLib::ReleaseTLibAttr
4510 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4513 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
4515 TLIBATTR
*pTLibAttr
)
4517 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4518 TRACE("freeing (%p)\n",This
);
4519 HeapFree(GetProcessHeap(),0,pTLibAttr
);
4523 /* ITypeLib2::GetCustData
4525 * gets the custom data
4527 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
4532 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4533 TLBCustData
*pCData
;
4535 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
4537 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4540 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4544 VariantInit( pVarVal
);
4545 VariantCopy( pVarVal
, &pCData
->data
);
4548 return E_INVALIDARG
; /* FIXME: correct? */
4551 /* ITypeLib2::GetLibStatistics
4553 * Returns statistics about a type library that are required for efficient
4554 * sizing of hash tables.
4557 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
4559 ULONG
*pcUniqueNames
,
4560 ULONG
*pcchUniqueNames
)
4562 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4564 FIXME("(%p): stub!\n", This
);
4566 if(pcUniqueNames
) *pcUniqueNames
=1;
4567 if(pcchUniqueNames
) *pcchUniqueNames
=1;
4571 /* ITypeLib2::GetDocumentation2
4573 * Retrieves the library's documentation string, the complete Help file name
4574 * and path, the localization context to use, and the context ID for the
4575 * library Help topic in the Help file.
4578 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
4582 BSTR
*pbstrHelpString
,
4583 DWORD
*pdwHelpStringContext
,
4584 BSTR
*pbstrHelpStringDll
)
4586 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4590 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
4592 /* the help string should be obtained from the helpstringdll,
4593 * using the _DLLGetDocumentation function, based on the supplied
4594 * lcid. Nice to do sometime...
4598 /* documentation for the typelib */
4600 *pbstrHelpString
=SysAllocString(This
->DocString
);
4601 if(pdwHelpStringContext
)
4602 *pdwHelpStringContext
=This
->dwHelpContext
;
4603 if(pbstrHelpStringDll
)
4604 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
4610 /* for a typeinfo */
4611 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
4613 if(SUCCEEDED(result
))
4615 ITypeInfo2
* pTInfo2
;
4616 result
= ITypeInfo_QueryInterface(pTInfo
,
4618 (LPVOID
*) &pTInfo2
);
4620 if(SUCCEEDED(result
))
4622 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
4626 pdwHelpStringContext
,
4627 pbstrHelpStringDll
);
4629 ITypeInfo2_Release(pTInfo2
);
4632 ITypeInfo_Release(pTInfo
);
4638 /* ITypeLib2::GetAllCustData
4640 * Gets all custom data items for the library.
4643 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
4645 CUSTDATA
*pCustData
)
4647 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4648 TLBCustData
*pCData
;
4650 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
4651 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
4652 if(pCustData
->prgCustData
){
4653 pCustData
->cCustData
=This
->ctCustData
;
4654 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
4655 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4656 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
4659 ERR(" OUT OF MEMORY!\n");
4660 return E_OUTOFMEMORY
;
4665 static const ITypeLib2Vtbl tlbvt
= {
4666 ITypeLib2_fnQueryInterface
,
4668 ITypeLib2_fnRelease
,
4669 ITypeLib2_fnGetTypeInfoCount
,
4670 ITypeLib2_fnGetTypeInfo
,
4671 ITypeLib2_fnGetTypeInfoType
,
4672 ITypeLib2_fnGetTypeInfoOfGuid
,
4673 ITypeLib2_fnGetLibAttr
,
4674 ITypeLib2_fnGetTypeComp
,
4675 ITypeLib2_fnGetDocumentation
,
4677 ITypeLib2_fnFindName
,
4678 ITypeLib2_fnReleaseTLibAttr
,
4680 ITypeLib2_fnGetCustData
,
4681 ITypeLib2_fnGetLibStatistics
,
4682 ITypeLib2_fnGetDocumentation2
,
4683 ITypeLib2_fnGetAllCustData
4687 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4689 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4691 return ITypeLib2_QueryInterface((ITypeLib
*)This
, riid
, ppv
);
4694 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4696 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4698 return ITypeLib2_AddRef((ITypeLib2
*)This
);
4701 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4703 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4705 return ITypeLib2_Release((ITypeLib2
*)This
);
4708 static HRESULT WINAPI
ITypeLibComp_fnBind(
4713 ITypeInfo
** ppTInfo
,
4714 DESCKIND
* pDescKind
,
4717 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4718 ITypeInfoImpl
*pTypeInfo
;
4720 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4722 *pDescKind
= DESCKIND_NONE
;
4723 pBindPtr
->lptcomp
= NULL
;
4726 for (pTypeInfo
= This
->pTypeInfo
; pTypeInfo
; pTypeInfo
= pTypeInfo
->next
)
4728 TRACE("testing %s\n", debugstr_w(pTypeInfo
->Name
));
4730 /* FIXME: check wFlags here? */
4731 /* FIXME: we should use a hash table to look this info up using lHash
4732 * instead of an O(n) search */
4733 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
) ||
4734 (pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
))
4736 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
, szName
))
4738 *pDescKind
= DESCKIND_TYPECOMP
;
4739 pBindPtr
->lptcomp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4740 ITypeComp_AddRef(pBindPtr
->lptcomp
);
4741 TRACE("module or enum: %s\n", debugstr_w(szName
));
4746 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
) ||
4747 (pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
))
4749 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4752 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4753 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
4755 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
4760 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_COCLASS
) &&
4761 (pTypeInfo
->TypeAttr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
4763 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4765 ITypeInfo
*subtypeinfo
;
4767 DESCKIND subdesckind
;
4769 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
4770 &subtypeinfo
, &subdesckind
, &subbindptr
);
4771 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
4773 TYPEDESC tdesc_appobject
=
4776 (TYPEDESC
*)pTypeInfo
->hreftype
4780 const VARDESC vardesc_appobject
=
4783 NULL
, /* lpstrSchema */
4798 VAR_STATIC
/* varkind */
4801 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
4803 /* cleanup things filled in by Bind call so we can put our
4804 * application object data in there instead */
4805 switch (subdesckind
)
4807 case DESCKIND_FUNCDESC
:
4808 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
4810 case DESCKIND_VARDESC
:
4811 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
4816 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
4818 if (pTypeInfo
->hreftype
== -1)
4819 FIXME("no hreftype for interface %p\n", pTypeInfo
);
4821 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
4825 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
4826 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
4827 ITypeInfo_AddRef(*ppTInfo
);
4833 TRACE("name not found %s\n", debugstr_w(szName
));
4837 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4841 ITypeInfo
** ppTInfo
,
4842 ITypeComp
** ppTComp
)
4844 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4845 ITypeInfoImpl
*pTypeInfo
;
4847 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4849 for (pTypeInfo
= This
->pTypeInfo
; pTypeInfo
; pTypeInfo
= pTypeInfo
->next
)
4851 /* FIXME: should use lHash to do the search */
4852 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
, szName
))
4854 TRACE("returning %p\n", pTypeInfo
);
4855 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->lpVtbl
;
4856 ITypeInfo_AddRef(*ppTInfo
);
4857 *ppTComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4858 ITypeComp_AddRef(*ppTComp
);
4863 TRACE("not found\n");
4869 static const ITypeCompVtbl tlbtcvt
=
4872 ITypeLibComp_fnQueryInterface
,
4873 ITypeLibComp_fnAddRef
,
4874 ITypeLibComp_fnRelease
,
4876 ITypeLibComp_fnBind
,
4877 ITypeLibComp_fnBindType
4880 /*================== ITypeInfo(2) Methods ===================================*/
4881 static ITypeInfo2
* ITypeInfo_Constructor(void)
4883 ITypeInfoImpl
* pTypeInfoImpl
;
4885 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4888 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4889 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4890 pTypeInfoImpl
->ref
=1;
4891 pTypeInfoImpl
->hreftype
= -1;
4892 pTypeInfoImpl
->TypeAttr
.memidConstructor
= MEMBERID_NIL
;
4893 pTypeInfoImpl
->TypeAttr
.memidDestructor
= MEMBERID_NIL
;
4895 TRACE("(%p)\n", pTypeInfoImpl
);
4896 return (ITypeInfo2
*) pTypeInfoImpl
;
4899 /* ITypeInfo::QueryInterface
4901 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4906 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4908 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4911 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4912 IsEqualIID(riid
,&IID_ITypeInfo
)||
4913 IsEqualIID(riid
,&IID_ITypeInfo2
))
4917 ITypeInfo_AddRef(iface
);
4918 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4921 TRACE("-- Interface: E_NOINTERFACE\n");
4922 return E_NOINTERFACE
;
4925 /* ITypeInfo::AddRef
4927 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4929 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4930 ULONG ref
= InterlockedIncrement(&This
->ref
);
4932 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4934 TRACE("(%p)->ref is %u\n",This
, ref
);
4938 /* ITypeInfo::Release
4940 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
4942 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4943 ULONG ref
= InterlockedDecrement(&This
->ref
);
4945 TRACE("(%p)->(%u)\n",This
, ref
);
4948 /* We don't release ITypeLib when ref=0 because
4949 it means that function is called by ITypeLib2_Release */
4950 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
4952 TLBFuncDesc
*pFInfo
, *pFInfoNext
;
4953 TLBVarDesc
*pVInfo
, *pVInfoNext
;
4954 TLBImplType
*pImpl
, *pImplNext
;
4956 TRACE("destroying ITypeInfo(%p)\n",This
);
4958 if (This
->no_free_data
)
4961 SysFreeString(This
->Name
);
4964 SysFreeString(This
->DocString
);
4965 This
->DocString
= NULL
;
4967 SysFreeString(This
->DllName
);
4968 This
->DllName
= NULL
;
4970 for (pFInfo
= This
->funclist
; pFInfo
; pFInfo
= pFInfoNext
)
4973 for(i
= 0;i
< pFInfo
->funcdesc
.cParams
; i
++)
4975 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[i
];
4976 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4978 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
4979 TLB_Free(elemdesc
->u
.paramdesc
.pparamdescex
);
4981 SysFreeString(pFInfo
->pParamDesc
[i
].Name
);
4983 TLB_Free(pFInfo
->funcdesc
.lprgelemdescParam
);
4984 TLB_Free(pFInfo
->pParamDesc
);
4985 TLB_FreeCustData(pFInfo
->pCustData
);
4986 if (HIWORD(pFInfo
->Entry
) != 0 && pFInfo
->Entry
!= (BSTR
)-1)
4987 SysFreeString(pFInfo
->Entry
);
4988 SysFreeString(pFInfo
->HelpString
);
4989 SysFreeString(pFInfo
->Name
);
4991 pFInfoNext
= pFInfo
->next
;
4994 for (pVInfo
= This
->varlist
; pVInfo
; pVInfo
= pVInfoNext
)
4996 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
4998 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
4999 TLB_Free(pVInfo
->vardesc
.u
.lpvarValue
);
5001 TLB_FreeCustData(pVInfo
->pCustData
);
5002 SysFreeString(pVInfo
->Name
);
5003 pVInfoNext
= pVInfo
->next
;
5006 for(pImpl
= This
->impltypelist
; pImpl
; pImpl
= pImplNext
)
5008 TLB_FreeCustData(pImpl
->pCustData
);
5009 pImplNext
= pImpl
->next
;
5012 TLB_FreeCustData(This
->pCustData
);
5017 ITypeInfo_Release((ITypeInfo
*)This
->next
);
5020 HeapFree(GetProcessHeap(),0,This
);
5026 /* ITypeInfo::GetTypeAttr
5028 * Retrieves a TYPEATTR structure that contains the attributes of the type
5032 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5033 LPTYPEATTR
*ppTypeAttr
)
5035 const ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5038 TRACE("(%p)\n",This
);
5040 size
= sizeof(**ppTypeAttr
);
5041 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5042 size
+= TLB_SizeTypeDesc(&This
->TypeAttr
.tdescAlias
, FALSE
);
5044 *ppTypeAttr
= HeapAlloc(GetProcessHeap(), 0, size
);
5046 return E_OUTOFMEMORY
;
5048 **ppTypeAttr
= This
->TypeAttr
;
5050 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5051 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5052 &This
->TypeAttr
.tdescAlias
, *ppTypeAttr
+ 1);
5054 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5055 /* This should include all the inherited funcs */
5056 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ sizeof(void *);
5057 (*ppTypeAttr
)->cbSizeVft
= 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5058 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5063 /* ITypeInfo::GetTypeComp
5065 * Retrieves the ITypeComp interface for the type description, which enables a
5066 * client compiler to bind to the type description's members.
5069 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5070 ITypeComp
* *ppTComp
)
5072 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5074 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5076 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
5077 ITypeComp_AddRef(*ppTComp
);
5081 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5083 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5084 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5085 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5089 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5092 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5093 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5095 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5096 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5097 *buffer
+= sizeof(PARAMDESCEX
);
5098 *pparamdescex_dest
= *pparamdescex_src
;
5099 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5100 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5101 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5104 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5108 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5110 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5111 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5114 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5118 SIZE_T size
= sizeof(*src
);
5122 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5123 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5124 for (i
= 0; i
< src
->cParams
; i
++)
5126 size
+= sizeof(ELEMDESC
);
5127 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5130 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5131 if (!dest
) return E_OUTOFMEMORY
;
5134 if (dispinterface
) /* overwrite funckind */
5135 dest
->funckind
= FUNC_DISPATCH
;
5136 buffer
= (char *)(dest
+ 1);
5138 dest
->lprgscode
= (SCODE
*)buffer
;
5139 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5140 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5142 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5145 SysFreeString((BSTR
)dest
);
5149 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5150 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5151 for (i
= 0; i
< src
->cParams
; i
++)
5153 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5159 /* undo the above actions */
5160 for (i
= i
- 1; i
>= 0; i
--)
5161 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5162 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5163 SysFreeString((BSTR
)dest
);
5167 /* special treatment for dispinterfaces: this makes functions appear
5168 * to return their [retval] value when it is really returning an
5170 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5172 if (dest
->cParams
&&
5173 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5175 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5176 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5178 ERR("elemdesc should have started with VT_PTR instead of:\n");
5180 dump_ELEMDESC(elemdesc
);
5181 return E_UNEXPECTED
;
5184 /* copy last parameter to the return value. we are using a flat
5185 * buffer so there is no danger of leaking memory in
5187 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5189 /* remove the last parameter */
5193 /* otherwise this function is made to appear to have no return
5195 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5203 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5205 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5206 const TLBFuncDesc
*pFDesc
;
5209 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
5214 *ppFuncDesc
= &pFDesc
->funcdesc
;
5218 return TYPE_E_ELEMENTNOTFOUND
;
5221 /* internal function to make the inherited interfaces' methods appear
5222 * part of the interface */
5223 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5224 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5226 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5228 UINT implemented_funcs
= 0;
5233 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5235 if(This
->impltypelist
)
5237 ITypeInfo
*pSubTypeInfo
;
5240 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pSubTypeInfo
);
5244 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5247 &sub_funcs
, hrefoffset
);
5248 implemented_funcs
+= sub_funcs
;
5249 ITypeInfo_Release(pSubTypeInfo
);
5252 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5256 *funcs
= implemented_funcs
+ This
->TypeAttr
.cFuncs
;
5260 if (index
< implemented_funcs
)
5261 return E_INVALIDARG
;
5262 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5266 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5268 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5271 switch (pTypeDesc
->vt
)
5273 case VT_USERDEFINED
:
5274 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5278 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5281 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5289 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5292 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5293 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5294 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5297 /* ITypeInfo::GetFuncDesc
5299 * Retrieves the FUNCDESC structure that contains information about a
5300 * specified function.
5303 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5304 LPFUNCDESC
*ppFuncDesc
)
5306 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5307 const FUNCDESC
*internal_funcdesc
;
5309 UINT hrefoffset
= 0;
5311 TRACE("(%p) index %d\n", This
, index
);
5313 if (This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5314 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5315 &internal_funcdesc
, NULL
,
5318 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5319 &internal_funcdesc
);
5322 WARN("description for function %d not found\n", index
);
5326 hr
= TLB_AllocAndInitFuncDesc(
5329 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
5331 if ((This
->TypeAttr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
5332 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5334 TRACE("-- 0x%08x\n", hr
);
5338 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5342 SIZE_T size
= sizeof(*src
);
5345 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
5346 if (src
->varkind
== VAR_CONST
)
5347 size
+= sizeof(VARIANT
);
5348 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
5350 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
5351 if (!dest
) return E_OUTOFMEMORY
;
5354 buffer
= (char *)(dest
+ 1);
5355 if (src
->lpstrSchema
)
5358 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
5359 len
= strlenW(src
->lpstrSchema
);
5360 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
5361 buffer
+= (len
+ 1) * sizeof(WCHAR
);
5364 if (src
->varkind
== VAR_CONST
)
5368 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
5369 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
5370 buffer
+= sizeof(VARIANT
);
5371 VariantInit(dest
->u
.lpvarValue
);
5372 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
5375 SysFreeString((BSTR
)dest_ptr
);
5379 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
5382 if (src
->varkind
== VAR_CONST
)
5383 VariantClear(dest
->u
.lpvarValue
);
5384 SysFreeString((BSTR
)dest
);
5391 /* ITypeInfo::GetVarDesc
5393 * Retrieves a VARDESC structure that describes the specified variable.
5396 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
5397 LPVARDESC
*ppVarDesc
)
5399 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5401 const TLBVarDesc
*pVDesc
;
5403 TRACE("(%p) index %d\n", This
, index
);
5405 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
5409 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
5411 return E_INVALIDARG
;
5414 /* ITypeInfo_GetNames
5416 * Retrieves the variable with the specified member ID (or the name of the
5417 * property or method and its parameters) that correspond to the specified
5420 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
5421 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
5423 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5424 const TLBFuncDesc
*pFDesc
;
5425 const TLBVarDesc
*pVDesc
;
5427 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
5428 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
5431 /* function found, now return function and parameter names */
5432 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
5435 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
5437 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
5443 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
5446 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
5451 if(This
->impltypelist
&&
5452 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
5453 /* recursive search */
5456 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
5458 if(SUCCEEDED(result
))
5460 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
5461 ITypeInfo_Release(pTInfo
);
5464 WARN("Could not search inherited interface!\n");
5468 WARN("no names found\n");
5471 return TYPE_E_ELEMENTNOTFOUND
;
5478 /* ITypeInfo::GetRefTypeOfImplType
5480 * If a type description describes a COM class, it retrieves the type
5481 * description of the implemented interface types. For an interface,
5482 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5486 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
5491 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5494 const TLBImplType
*pImpl
= This
->impltypelist
;
5496 TRACE("(%p) index %d\n", This
, index
);
5497 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
5501 /* only valid on dual interfaces;
5502 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5504 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
5506 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
5512 hr
= TYPE_E_ELEMENTNOTFOUND
;
5515 else if(index
== 0 && This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5517 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5518 *pRefType
= This
->pTypeLib
->dispatch_href
;
5522 /* get element n from linked list */
5523 for(i
=0; pImpl
&& i
<index
; i
++)
5525 pImpl
= pImpl
->next
;
5529 *pRefType
= pImpl
->hRef
;
5531 hr
= TYPE_E_ELEMENTNOTFOUND
;
5537 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
5539 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
5545 /* ITypeInfo::GetImplTypeFlags
5547 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5548 * or base interface in a type description.
5550 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
5551 UINT index
, INT
*pImplTypeFlags
)
5553 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5557 TRACE("(%p) index %d\n", This
, index
);
5558 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
5559 i
++, pImpl
=pImpl
->next
)
5561 if(i
==index
&& pImpl
){
5562 *pImplTypeFlags
=pImpl
->implflags
;
5566 return TYPE_E_ELEMENTNOTFOUND
;
5570 * Maps between member names and member IDs, and parameter names and
5573 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
5574 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
5576 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5577 const TLBFuncDesc
*pFDesc
;
5578 const TLBVarDesc
*pVDesc
;
5582 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
5585 /* init out parameters in case of failure */
5586 for (i
= 0; i
< cNames
; i
++)
5587 pMemId
[i
] = MEMBERID_NIL
;
5589 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
5591 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
5592 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
5593 for(i
=1; i
< cNames
; i
++){
5594 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
5595 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
5597 if( j
<pFDesc
->funcdesc
.cParams
)
5600 ret
=DISP_E_UNKNOWNNAME
;
5602 TRACE("-- 0x%08x\n", ret
);
5606 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
5607 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
5608 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
5612 /* not found, see if it can be found in an inherited interface */
5613 if(This
->impltypelist
) {
5614 /* recursive search */
5616 ret
=ITypeInfo_GetRefTypeInfo(iface
,
5617 This
->impltypelist
->hRef
, &pTInfo
);
5619 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
5620 ITypeInfo_Release(pTInfo
);
5623 WARN("Could not search inherited interface!\n");
5625 WARN("no names found\n");
5626 return DISP_E_UNKNOWNNAME
;
5632 extern DWORD CDECL
call_method( void *func
, int nb_args
, const DWORD
*args
);
5633 __ASM_GLOBAL_FUNC( call_method
,
5635 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5636 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5637 "movl %esp,%ebp\n\t"
5638 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5640 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5642 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5643 "movl 12(%ebp),%edx\n\t"
5646 "subl %edx,%esp\n\t"
5647 "andl $~15,%esp\n\t"
5648 "movl 12(%ebp),%ecx\n\t"
5649 "movl 16(%ebp),%esi\n\t"
5650 "movl %esp,%edi\n\t"
5653 "1:\tcall *8(%ebp)\n\t"
5654 "leal -8(%ebp),%esp\n\t"
5656 __ASM_CFI(".cfi_same_value %edi\n\t")
5658 __ASM_CFI(".cfi_same_value %esi\n\t")
5660 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5661 __ASM_CFI(".cfi_same_value %ebp\n\t")
5664 /* ITypeInfo::Invoke
5666 * Invokes a method, or accesses a property of an object, that implements the
5667 * interface described by the type description.
5670 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
5673 if (TRACE_ON(ole
)) {
5675 TRACE("Calling %p(",func
);
5676 for (i
=0;i
<nrargs
;i
++) TRACE("%08x,",args
[i
]);
5683 res
= call_method( func
, nrargs
, args
);
5686 FIXME("unsupported calling convention %d\n",callconv
);
5690 TRACE("returns %08x\n",res
);
5694 /* The size of the argument on the stack in DWORD units (in all x86 call
5695 * convetions the arguments on the stack are DWORD-aligned)
5697 static int _dispargsize(VARTYPE vt
)
5702 return 8/sizeof(DWORD
);
5704 return sizeof(double)/sizeof(DWORD
);
5706 return (sizeof(DECIMAL
)+3)/sizeof(DWORD
);
5708 return sizeof(CY
)/sizeof(DWORD
);
5710 return sizeof(DATE
)/sizeof(DWORD
);
5712 return (sizeof(VARIANT
)+3)/sizeof(DWORD
);
5714 FIXME("VT_RECORD not implemented\n");
5720 #endif /* __i386__ */
5722 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5725 ITypeInfo
*tinfo2
= NULL
;
5726 TYPEATTR
*tattr
= NULL
;
5728 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
5731 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5733 tdesc
->u
.hreftype
, hr
);
5736 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
5739 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
5740 ITypeInfo_Release(tinfo2
);
5744 switch (tattr
->typekind
)
5751 tdesc
= &tattr
->tdescAlias
;
5752 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
5755 case TKIND_INTERFACE
:
5756 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
5762 case TKIND_DISPATCH
:
5771 FIXME("TKIND_RECORD unhandled.\n");
5776 FIXME("TKIND_UNION unhandled.\n");
5781 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
5785 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
5786 ITypeInfo_Release(tinfo2
);
5790 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5794 /* enforce only one level of pointer indirection */
5795 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
5797 tdesc
= tdesc
->u
.lptdesc
;
5799 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5800 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5801 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5802 if ((tdesc
->vt
== VT_USERDEFINED
) ||
5803 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
5805 VARTYPE vt_userdefined
= 0;
5806 const TYPEDESC
*tdesc_userdefined
= tdesc
;
5807 if (tdesc
->vt
== VT_PTR
)
5809 vt_userdefined
= VT_BYREF
;
5810 tdesc_userdefined
= tdesc
->u
.lptdesc
;
5812 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
5814 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
5815 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
5817 *vt
|= vt_userdefined
;
5829 case VT_USERDEFINED
:
5830 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
5837 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
5838 hr
= DISP_E_BADVARTYPE
;
5842 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
5857 /***********************************************************************
5858 * DispCallFunc (OLEAUT32.@)
5860 * Invokes a function of the specified calling convention, passing the
5861 * specified arguments and returns the result.
5864 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5865 * oVft [I] The offset in the vtable. See notes.
5866 * cc [I] Calling convention of the function to call.
5867 * vtReturn [I] The return type of the function.
5868 * cActuals [I] Number of parameters.
5869 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5870 * prgpvarg [I] The arguments to pass.
5871 * pvargResult [O] The return value of the function. Can be NULL.
5875 * Failure: HRESULT code.
5878 * The HRESULT return value of this function is not affected by the return
5879 * value of the user supplied function, which is returned in pvargResult.
5881 * If pvInstance is NULL then a non-object function is to be called and oVft
5882 * is the address of the function to call.
5884 * The cc parameter can be one of the following values:
5897 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
5898 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
5901 int argsize
, argspos
;
5906 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5907 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
5908 pvargResult
, V_VT(pvargResult
));
5912 argsize
++; /* for This pointer */
5914 for (i
=0;i
<cActuals
;i
++)
5916 TRACE("arg %u: type %d, size %d\n",i
,prgvt
[i
],_dispargsize(prgvt
[i
]));
5917 dump_Variant(prgpvarg
[i
]);
5918 argsize
+= _dispargsize(prgvt
[i
]);
5920 args
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
5925 args
[0] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
5929 for (i
=0;i
<cActuals
;i
++)
5931 VARIANT
*arg
= prgpvarg
[i
];
5932 TRACE("Storing arg %u (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
5933 if (prgvt
[i
] == VT_VARIANT
)
5934 memcpy(&args
[argspos
], arg
, _dispargsize(prgvt
[i
]) * sizeof(DWORD
));
5936 memcpy(&args
[argspos
], &V_NONE(arg
), _dispargsize(prgvt
[i
]) * sizeof(DWORD
));
5937 argspos
+= _dispargsize(prgvt
[i
]);
5942 FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
5943 hres
= _invoke(vtable
[oVft
/sizeof(void *)], cc
, argsize
, args
);
5946 /* if we aren't invoking an object then the function pointer is stored
5948 hres
= _invoke((FARPROC
)oVft
, cc
, argsize
, args
);
5950 if (pvargResult
&& (vtReturn
!= VT_EMPTY
))
5952 TRACE("Method returned 0x%08x\n",hres
);
5953 V_VT(pvargResult
) = vtReturn
;
5954 V_UI4(pvargResult
) = hres
;
5956 HeapFree(GetProcessHeap(),0,args
);
5959 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
5960 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
5965 #define INVBUF_ELEMENT_SIZE \
5966 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5967 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5968 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5969 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5970 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5971 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5972 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5973 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5975 static HRESULT WINAPI
ITypeInfo_fnInvoke(
5980 DISPPARAMS
*pDispParams
,
5981 VARIANT
*pVarResult
,
5982 EXCEPINFO
*pExcepInfo
,
5985 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5987 unsigned int var_index
;
5990 const TLBFuncDesc
*pFuncInfo
;
5992 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5993 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
5998 ERR("NULL pDispParams not allowed\n");
5999 return E_INVALIDARG
;
6002 dump_DispParms(pDispParams
);
6004 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6006 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6007 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6008 return E_INVALIDARG
;
6011 /* we do this instead of using GetFuncDesc since it will return a fake
6012 * FUNCDESC for dispinterfaces and we want the real function description */
6013 for (pFuncInfo
= This
->funclist
; pFuncInfo
; pFuncInfo
=pFuncInfo
->next
)
6014 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6015 (wFlags
& pFuncInfo
->funcdesc
.invkind
))
6019 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6023 TRACE("invoking:\n");
6024 dump_TLBFuncDescOne(pFuncInfo
);
6027 switch (func_desc
->funckind
) {
6028 case FUNC_PUREVIRTUAL
:
6029 case FUNC_VIRTUAL
: {
6030 void *buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6032 VARIANT retval
; /* pointer for storing byref retvals in */
6033 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6034 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6035 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6036 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6037 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6038 UINT vargs_converted
=0;
6042 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6044 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6046 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6047 hres
= DISP_E_PARAMNOTFOUND
;
6050 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6052 rgdispidNamedArgs
++;
6055 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6057 ERR("functions with the vararg attribute do not support named arguments\n");
6058 hres
= DISP_E_NONAMEDARGS
;
6062 for (i
= 0; i
< func_desc
->cParams
; i
++)
6064 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6065 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6070 TRACE("changing args\n");
6071 for (i
= 0; i
< func_desc
->cParams
; i
++)
6073 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6074 VARIANTARG
*src_arg
;
6076 if (wParamFlags
& PARAMFLAG_FLCID
)
6079 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6081 V_I4(arg
) = This
->pTypeLib
->lcid
;
6089 for (j
= 0; j
< cNamedArgs
; j
++)
6090 if (rgdispidNamedArgs
[j
] == i
)
6092 src_arg
= &pDispParams
->rgvarg
[j
];
6098 src_arg
= vargs_converted
< pDispParams
->cArgs
? &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
] : NULL
;
6102 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6104 /* under most conditions the caller is not allowed to
6105 * pass in a dispparam arg in the index of what would be
6106 * the retval parameter. however, there is an exception
6107 * where the extra parameter is used in an extra
6108 * IDispatch::Invoke below */
6109 if ((i
< pDispParams
->cArgs
) &&
6110 ((func_desc
->cParams
!= 1) || !pVarResult
||
6111 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
6113 hres
= DISP_E_BADPARAMCOUNT
;
6117 /* note: this check is placed so that if the caller passes
6118 * in a VARIANTARG for the retval we just ignore it, like
6120 if (i
== func_desc
->cParams
- 1)
6123 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6124 memset(arg
, 0, sizeof(*arg
));
6125 V_VT(arg
) = rgvt
[i
];
6126 memset(&retval
, 0, sizeof(retval
));
6127 V_BYREF(arg
) = &retval
;
6131 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
6132 hres
= E_UNEXPECTED
;
6138 dump_Variant(src_arg
);
6140 if (rgvt
[i
] == VT_VARIANT
)
6141 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
6142 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
6144 if (rgvt
[i
] == V_VT(src_arg
))
6145 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
6148 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6149 if (wParamFlags
& PARAMFLAG_FIN
)
6150 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
6151 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
6153 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6155 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
6158 SAFEARRAYBOUND bound
;
6162 bound
.cElements
= pDispParams
->cArgs
-i
;
6163 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
6165 ERR("SafeArrayCreate failed\n");
6168 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6171 ERR("SafeArrayAccessData failed with %x\n", hres
);
6174 for (j
= 0; j
< bound
.cElements
; j
++)
6175 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
6176 hres
= SafeArrayUnaccessData(a
);
6179 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6182 V_ARRAY(&rgvarg
[i
]) = a
;
6183 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6185 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
6187 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6188 if (wParamFlags
& PARAMFLAG_FIN
)
6189 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
6191 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
6192 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
6193 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6195 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
6197 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
6198 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6202 /* FIXME: this doesn't work for VT_BYREF arguments if
6203 * they are not the same type as in the paramdesc */
6204 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
6205 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
6206 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6211 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
6212 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
6213 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
6216 prgpvarg
[i
] = &rgvarg
[i
];
6218 else if (wParamFlags
& PARAMFLAG_FOPT
)
6221 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6222 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6224 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
6230 VARIANTARG
*missing_arg
;
6231 /* if the function wants a pointer to a variant then
6232 * set that up, otherwise just pass the VT_ERROR in
6233 * the argument by value */
6234 if (rgvt
[i
] & VT_BYREF
)
6236 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
6237 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
6238 V_VARIANTREF(arg
) = missing_arg
;
6242 V_VT(missing_arg
) = VT_ERROR
;
6243 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
6248 hres
= DISP_E_BADPARAMCOUNT
;
6252 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6254 /* VT_VOID is a special case for return types, so it is not
6255 * handled in the general function */
6256 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
6257 V_VT(&varresult
) = VT_EMPTY
;
6260 V_VT(&varresult
) = 0;
6261 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
6262 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6265 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
, func_desc
->callconv
,
6266 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
6267 prgpvarg
, &varresult
);
6269 vargs_converted
= 0;
6271 for (i
= 0; i
< func_desc
->cParams
; i
++)
6273 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6274 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6276 if (wParamFlags
& PARAMFLAG_FLCID
)
6278 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
6282 TRACE("[retval] value: ");
6283 dump_Variant(prgpvarg
[i
]);
6288 VariantInit(pVarResult
);
6289 /* deref return value */
6290 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
6293 VARIANT_ClearInd(prgpvarg
[i
]);
6295 else if (vargs_converted
< pDispParams
->cArgs
)
6297 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6298 if (wParamFlags
& PARAMFLAG_FOUT
)
6300 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
6302 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
6306 ERR("failed to convert param %d to vt %d\n", i
,
6307 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
6312 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
6313 func_desc
->cParamsOpt
< 0 &&
6314 i
== func_desc
->cParams
-1)
6316 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
6319 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
6322 ERR("SafeArrayGetUBound failed with %x\n", hres
);
6325 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6328 ERR("SafeArrayAccessData failed with %x\n", hres
);
6331 for (j
= 0; j
<= ubound
; j
++)
6332 VariantClear(&v
[j
]);
6333 hres
= SafeArrayUnaccessData(a
);
6336 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6340 VariantClear(&rgvarg
[i
]);
6343 else if (wParamFlags
& PARAMFLAG_FOPT
)
6345 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6346 VariantClear(&rgvarg
[i
]);
6349 VariantClear(&missing_arg
[i
]);
6352 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
6354 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
6355 hres
= DISP_E_EXCEPTION
;
6358 IErrorInfo
*pErrorInfo
;
6359 pExcepInfo
->scode
= V_ERROR(&varresult
);
6360 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
6362 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
6363 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
6364 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
6365 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
6367 IErrorInfo_Release(pErrorInfo
);
6371 if (V_VT(&varresult
) != VT_ERROR
)
6373 TRACE("varresult value: ");
6374 dump_Variant(&varresult
);
6378 VariantClear(pVarResult
);
6379 *pVarResult
= varresult
;
6382 VariantClear(&varresult
);
6385 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
6386 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
6387 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
6388 (pDispParams
->cArgs
!= 0))
6390 if (V_VT(pVarResult
) == VT_DISPATCH
)
6392 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
6393 /* Note: not VariantClear; we still need the dispatch
6394 * pointer to be valid */
6395 VariantInit(pVarResult
);
6396 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
6397 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
6398 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
6399 IDispatch_Release(pDispatch
);
6403 VariantClear(pVarResult
);
6404 hres
= DISP_E_NOTACOLLECTION
;
6409 HeapFree(GetProcessHeap(), 0, buffer
);
6412 case FUNC_DISPATCH
: {
6415 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
6416 if (SUCCEEDED(hres
)) {
6417 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6418 hres
= IDispatch_Invoke(
6419 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
6420 pVarResult
,pExcepInfo
,pArgErr
6423 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
6424 IDispatch_Release(disp
);
6426 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6430 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
6435 TRACE("-- 0x%08x\n", hres
);
6438 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
6441 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
6442 if(FAILED(hres
)) return hres
;
6444 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6445 dump_VARDESC(var_desc
);
6446 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
6450 /* not found, look for it in inherited interfaces */
6451 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
6452 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
6453 if(This
->impltypelist
) {
6454 /* recursive search */
6456 hres
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pTInfo
);
6457 if(SUCCEEDED(hres
)){
6458 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
6459 ITypeInfo_Release(pTInfo
);
6462 WARN("Could not search inherited interface!\n");
6465 ERR("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
6466 return DISP_E_MEMBERNOTFOUND
;
6469 /* ITypeInfo::GetDocumentation
6471 * Retrieves the documentation string, the complete Help file name and path,
6472 * and the context ID for the Help topic for a specified type description.
6474 * (Can be tested by the Visual Basic Editor in Word for instance.)
6476 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
6477 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
6478 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
6480 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6481 const TLBFuncDesc
*pFDesc
;
6482 const TLBVarDesc
*pVDesc
;
6483 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6484 " HelpContext(%p) HelpFile(%p)\n",
6485 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6486 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
6488 *pBstrName
=SysAllocString(This
->Name
);
6490 *pBstrDocString
=SysAllocString(This
->DocString
);
6492 *pdwHelpContext
=This
->dwHelpContext
;
6494 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
6496 }else {/* for a member */
6497 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6498 if(pFDesc
->funcdesc
.memid
==memid
){
6500 *pBstrName
= SysAllocString(pFDesc
->Name
);
6502 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
6504 *pdwHelpContext
=pFDesc
->helpcontext
;
6507 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
6508 if(pVDesc
->vardesc
.memid
==memid
){
6510 *pBstrName
= SysAllocString(pVDesc
->Name
);
6512 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
6514 *pdwHelpContext
=pVDesc
->HelpContext
;
6519 if(This
->impltypelist
&&
6520 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
6521 /* recursive search */
6524 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
6526 if(SUCCEEDED(result
)) {
6527 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
6528 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6529 ITypeInfo_Release(pTInfo
);
6532 WARN("Could not search inherited interface!\n");
6535 WARN("member %d not found\n", memid
);
6536 return TYPE_E_ELEMENTNOTFOUND
;
6539 /* ITypeInfo::GetDllEntry
6541 * Retrieves a description or specification of an entry point for a function
6544 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
6545 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
6548 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6549 const TLBFuncDesc
*pFDesc
;
6551 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
6553 if (pBstrDllName
) *pBstrDllName
= NULL
;
6554 if (pBstrName
) *pBstrName
= NULL
;
6555 if (pwOrdinal
) *pwOrdinal
= 0;
6557 if (This
->TypeAttr
.typekind
!= TKIND_MODULE
)
6558 return TYPE_E_BADMODULEKIND
;
6560 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6561 if(pFDesc
->funcdesc
.memid
==memid
){
6562 dump_TypeInfo(This
);
6564 dump_TLBFuncDescOne(pFDesc
);
6567 *pBstrDllName
= SysAllocString(This
->DllName
);
6569 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
6571 *pBstrName
= SysAllocString(pFDesc
->Entry
);
6579 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
6582 return TYPE_E_ELEMENTNOTFOUND
;
6585 /* internal function to make the inherited interfaces' methods appear
6586 * part of the interface */
6587 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
6588 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
6590 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6593 TRACE("%p, 0x%x\n", iface
, *hRefType
);
6595 if (This
->impltypelist
&& (*hRefType
& DISPATCH_HREF_MASK
))
6597 ITypeInfo
*pSubTypeInfo
;
6599 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pSubTypeInfo
);
6603 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
6605 ITypeInfo_Release(pSubTypeInfo
);
6609 *hRefType
-= DISPATCH_HREF_OFFSET
;
6611 if (!(*hRefType
& DISPATCH_HREF_MASK
))
6612 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
6617 /* ITypeInfo::GetRefTypeInfo
6619 * If a type description references other type descriptions, it retrieves
6620 * the referenced type descriptions.
6622 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
6625 ITypeInfo
**ppTInfo
)
6627 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6628 HRESULT result
= E_FAIL
;
6630 if ((This
->hreftype
!= -1) && (This
->hreftype
== hRefType
))
6632 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6633 ITypeInfo_AddRef(*ppTInfo
);
6636 else if (hRefType
== -1 &&
6637 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
6638 (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
6640 /* when we meet a DUAL dispinterface, we must create the interface
6643 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
6646 /* the interface version contains the same information as the dispinterface
6647 * copy the contents of the structs.
6649 *pTypeInfoImpl
= *This
;
6650 pTypeInfoImpl
->ref
= 0;
6652 /* change the type to interface */
6653 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
6655 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
6657 /* we use data structures from This, so we need to keep a reference
6658 * to it to stop it being destroyed and signal to the new instance to
6659 * not free its data structures when it is destroyed */
6660 pTypeInfoImpl
->no_free_data
= TRUE
;
6661 pTypeInfoImpl
->next
= This
;
6662 ITypeInfo_AddRef((ITypeInfo
*) This
);
6664 ITypeInfo_AddRef(*ppTInfo
);
6668 } else if ((hRefType
!= -1) && (hRefType
& DISPATCH_HREF_MASK
) &&
6669 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
))
6671 HREFTYPE href_dispatch
= hRefType
;
6672 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
6674 TLBRefType
*ref_type
;
6675 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
6677 if(ref_type
->reference
== hRefType
)
6680 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
6682 FIXME("Can't find pRefType for ref %x\n", hRefType
);
6685 if(hRefType
!= -1) {
6686 ITypeLib
*pTLib
= NULL
;
6688 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
6690 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
6692 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
6693 TRACE("typeinfo in imported typelib that is already loaded\n");
6694 pTLib
= (ITypeLib
*)ref_type
->pImpTLInfo
->pImpTypeLib
;
6695 ITypeLib2_AddRef(pTLib
);
6698 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6699 result
= LoadRegTypeLib( &ref_type
->pImpTLInfo
->guid
,
6700 ref_type
->pImpTLInfo
->wVersionMajor
,
6701 ref_type
->pImpTLInfo
->wVersionMinor
,
6702 ref_type
->pImpTLInfo
->lcid
,
6705 if(FAILED(result
)) {
6706 BSTR libnam
=SysAllocString(ref_type
->pImpTLInfo
->name
);
6707 result
=LoadTypeLib(libnam
, &pTLib
);
6708 SysFreeString(libnam
);
6710 if(SUCCEEDED(result
)) {
6711 ref_type
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
6712 ITypeLib2_AddRef(pTLib
);
6716 if(SUCCEEDED(result
)) {
6717 if(ref_type
->index
== TLB_REF_USE_GUID
)
6718 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
6722 result
= ITypeLib2_GetTypeInfo(pTLib
, ref_type
->index
,
6726 ITypeLib2_Release(pTLib
);
6731 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
6732 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
6736 /* ITypeInfo::AddressOfMember
6738 * Retrieves the addresses of static functions or variables, such as those
6741 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
6742 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
6744 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6750 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
6752 hr
= ITypeInfo_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
6756 module
= LoadLibraryW(dll
);
6759 ERR("couldn't load %s\n", debugstr_w(dll
));
6761 SysFreeString(entry
);
6762 return STG_E_FILENOTFOUND
;
6764 /* FIXME: store library somewhere where we can free it */
6769 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
6770 entryA
= HeapAlloc(GetProcessHeap(), 0, len
);
6771 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
6773 *ppv
= GetProcAddress(module
, entryA
);
6775 ERR("function not found %s\n", debugstr_a(entryA
));
6777 HeapFree(GetProcessHeap(), 0, entryA
);
6781 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
6783 ERR("function not found %d\n", ordinal
);
6787 SysFreeString(entry
);
6790 return TYPE_E_DLLFUNCTIONNOTFOUND
;
6795 /* ITypeInfo::CreateInstance
6797 * Creates a new instance of a type that describes a component object class
6800 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
6801 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
6803 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6807 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
6813 WARN("Not able to aggregate\n");
6814 return CLASS_E_NOAGGREGATION
;
6817 hr
= ITypeInfo_GetTypeAttr(iface
, &pTA
);
6818 if(FAILED(hr
)) return hr
;
6820 if(pTA
->typekind
!= TKIND_COCLASS
)
6822 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
6828 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
6831 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
6832 TRACE("GetActiveObject rets %08x\n", hr
);
6835 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
6836 IUnknown_Release(pUnk
);
6841 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
6842 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
6846 ITypeInfo_ReleaseTypeAttr(iface
, pTA
);
6850 /* ITypeInfo::GetMops
6852 * Retrieves marshalling information.
6854 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
6857 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6858 FIXME("(%p) stub!\n", This
);
6862 /* ITypeInfo::GetContainingTypeLib
6864 * Retrieves the containing type library and the index of the type description
6865 * within that type library.
6867 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
6868 ITypeLib
* *ppTLib
, UINT
*pIndex
)
6870 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6872 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6874 *pIndex
=This
->index
;
6875 TRACE("returning pIndex=%d\n", *pIndex
);
6879 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
6880 ITypeLib2_AddRef(*ppTLib
);
6881 TRACE("returning ppTLib=%p\n", *ppTLib
);
6887 /* ITypeInfo::ReleaseTypeAttr
6889 * Releases a TYPEATTR previously returned by GetTypeAttr.
6892 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
6893 TYPEATTR
* pTypeAttr
)
6895 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6896 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
6897 HeapFree(GetProcessHeap(), 0, pTypeAttr
);
6900 /* ITypeInfo::ReleaseFuncDesc
6902 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6904 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
6906 FUNCDESC
*pFuncDesc
)
6908 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6911 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
6913 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6914 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
6915 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
6917 SysFreeString((BSTR
)pFuncDesc
);
6920 /* ITypeInfo::ReleaseVarDesc
6922 * Releases a VARDESC previously returned by GetVarDesc.
6924 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
6927 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6928 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
6930 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
6931 if (pVarDesc
->varkind
== VAR_CONST
)
6932 VariantClear(pVarDesc
->u
.lpvarValue
);
6933 SysFreeString((BSTR
)pVarDesc
);
6936 /* ITypeInfo2::GetTypeKind
6938 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6941 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
6942 TYPEKIND
*pTypeKind
)
6944 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6945 *pTypeKind
=This
->TypeAttr
.typekind
;
6946 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
6950 /* ITypeInfo2::GetTypeFlags
6952 * Returns the type flags without any allocations. This returns a DWORD type
6953 * flag, which expands the type flags without growing the TYPEATTR (type
6957 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
6959 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6960 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
6961 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
6965 /* ITypeInfo2::GetFuncIndexOfMemId
6966 * Binds to a specific member based on a known DISPID, where the member name
6967 * is not known (for example, when binding to a default member).
6970 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
6971 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
6973 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6974 const TLBFuncDesc
*pFuncInfo
;
6978 for(i
= 0, pFuncInfo
= This
->funclist
; pFuncInfo
; i
++, pFuncInfo
=pFuncInfo
->next
)
6979 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
6985 result
= TYPE_E_ELEMENTNOTFOUND
;
6987 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
6988 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
6992 /* TypeInfo2::GetVarIndexOfMemId
6994 * Binds to a specific member based on a known DISPID, where the member name
6995 * is not known (for example, when binding to a default member).
6998 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
6999 MEMBERID memid
, UINT
*pVarIndex
)
7001 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7002 TLBVarDesc
*pVarInfo
;
7005 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
7006 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
7012 result
= TYPE_E_ELEMENTNOTFOUND
;
7014 TRACE("(%p) memid 0x%08x -> %s\n", This
,
7015 memid
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7019 /* ITypeInfo2::GetCustData
7021 * Gets the custom data
7023 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7028 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7029 TLBCustData
*pCData
;
7031 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
7032 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7034 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7036 VariantInit( pVarVal
);
7038 VariantCopy( pVarVal
, &pCData
->data
);
7040 VariantClear( pVarVal
);
7044 /* ITypeInfo2::GetFuncCustData
7046 * Gets the custom data
7048 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
7054 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7055 TLBCustData
*pCData
=NULL
;
7056 TLBFuncDesc
* pFDesc
;
7058 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
7059 pFDesc
=pFDesc
->next
);
7062 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
7063 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7065 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7068 VariantInit( pVarVal
);
7069 VariantCopy( pVarVal
, &pCData
->data
);
7072 return E_INVALIDARG
; /* FIXME: correct? */
7075 /* ITypeInfo2::GetParamCustData
7077 * Gets the custom data
7079 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
7086 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7087 TLBCustData
*pCData
=NULL
;
7088 TLBFuncDesc
* pFDesc
;
7091 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
7093 if(pFDesc
&& indexParam
<pFDesc
->funcdesc
.cParams
)
7094 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
7095 pCData
= pCData
->next
)
7096 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7098 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7102 VariantInit( pVarVal
);
7103 VariantCopy( pVarVal
, &pCData
->data
);
7106 return E_INVALIDARG
; /* FIXME: correct? */
7109 /* ITypeInfo2::GetVarCustData
7111 * Gets the custom data
7113 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
7119 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7120 TLBCustData
*pCData
=NULL
;
7121 TLBVarDesc
* pVDesc
;
7124 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
7128 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
7130 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7134 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7138 VariantInit( pVarVal
);
7139 VariantCopy( pVarVal
, &pCData
->data
);
7142 return E_INVALIDARG
; /* FIXME: correct? */
7145 /* ITypeInfo2::GetImplCustData
7147 * Gets the custom data
7149 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
7155 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7156 TLBCustData
*pCData
=NULL
;
7157 TLBImplType
* pRDesc
;
7160 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
7164 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
7166 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7170 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7174 VariantInit( pVarVal
);
7175 VariantCopy( pVarVal
, &pCData
->data
);
7178 return E_INVALIDARG
; /* FIXME: correct? */
7181 /* ITypeInfo2::GetDocumentation2
7183 * Retrieves the documentation string, the complete Help file name and path,
7184 * the localization context to use, and the context ID for the library Help
7185 * topic in the Help file.
7188 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
7192 BSTR
*pbstrHelpString
,
7193 DWORD
*pdwHelpStringContext
,
7194 BSTR
*pbstrHelpStringDll
)
7196 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7197 const TLBFuncDesc
*pFDesc
;
7198 const TLBVarDesc
*pVDesc
;
7199 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7200 "HelpStringContext(%p) HelpStringDll(%p)\n",
7201 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
7202 pbstrHelpStringDll
);
7203 /* the help string should be obtained from the helpstringdll,
7204 * using the _DLLGetDocumentation function, based on the supplied
7205 * lcid. Nice to do sometime...
7207 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7209 *pbstrHelpString
=SysAllocString(This
->Name
);
7210 if(pdwHelpStringContext
)
7211 *pdwHelpStringContext
=This
->dwHelpStringContext
;
7212 if(pbstrHelpStringDll
)
7213 *pbstrHelpStringDll
=
7214 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7216 }else {/* for a member */
7217 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
7218 if(pFDesc
->funcdesc
.memid
==memid
){
7220 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
7221 if(pdwHelpStringContext
)
7222 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
7223 if(pbstrHelpStringDll
)
7224 *pbstrHelpStringDll
=
7225 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7228 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
7229 if(pVDesc
->vardesc
.memid
==memid
){
7231 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
7232 if(pdwHelpStringContext
)
7233 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
7234 if(pbstrHelpStringDll
)
7235 *pbstrHelpStringDll
=
7236 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7240 return TYPE_E_ELEMENTNOTFOUND
;
7243 /* ITypeInfo2::GetAllCustData
7245 * Gets all custom data items for the Type info.
7248 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
7250 CUSTDATA
*pCustData
)
7252 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7253 TLBCustData
*pCData
;
7256 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
7258 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
7259 if(pCustData
->prgCustData
){
7260 pCustData
->cCustData
=This
->ctCustData
;
7261 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
7262 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7263 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
7266 ERR(" OUT OF MEMORY!\n");
7267 return E_OUTOFMEMORY
;
7272 /* ITypeInfo2::GetAllFuncCustData
7274 * Gets all custom data items for the specified Function
7277 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
7280 CUSTDATA
*pCustData
)
7282 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7283 TLBCustData
*pCData
;
7284 TLBFuncDesc
* pFDesc
;
7286 TRACE("(%p) index %d\n", This
, index
);
7287 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
7288 pFDesc
=pFDesc
->next
)
7291 pCustData
->prgCustData
=
7292 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
7293 if(pCustData
->prgCustData
){
7294 pCustData
->cCustData
=pFDesc
->ctCustData
;
7295 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
7296 pCData
= pCData
->next
){
7297 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7298 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7302 ERR(" OUT OF MEMORY!\n");
7303 return E_OUTOFMEMORY
;
7307 return TYPE_E_ELEMENTNOTFOUND
;
7310 /* ITypeInfo2::GetAllParamCustData
7312 * Gets all custom data items for the Functions
7315 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
7316 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
7318 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7319 TLBCustData
*pCData
=NULL
;
7320 TLBFuncDesc
* pFDesc
;
7322 TRACE("(%p) index %d\n", This
, indexFunc
);
7323 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
7324 pFDesc
=pFDesc
->next
)
7326 if(pFDesc
&& indexParam
<pFDesc
->funcdesc
.cParams
){
7327 pCustData
->prgCustData
=
7328 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
7329 sizeof(CUSTDATAITEM
));
7330 if(pCustData
->prgCustData
){
7331 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
7332 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
7333 pCData
; i
++, pCData
= pCData
->next
){
7334 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7335 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7339 ERR(" OUT OF MEMORY!\n");
7340 return E_OUTOFMEMORY
;
7344 return TYPE_E_ELEMENTNOTFOUND
;
7347 /* ITypeInfo2::GetAllVarCustData
7349 * Gets all custom data items for the specified Variable
7352 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
7353 UINT index
, CUSTDATA
*pCustData
)
7355 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7356 TLBCustData
*pCData
;
7357 TLBVarDesc
* pVDesc
;
7359 TRACE("(%p) index %d\n", This
, index
);
7360 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
7361 pVDesc
=pVDesc
->next
)
7364 pCustData
->prgCustData
=
7365 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
7366 if(pCustData
->prgCustData
){
7367 pCustData
->cCustData
=pVDesc
->ctCustData
;
7368 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
7369 pCData
= pCData
->next
){
7370 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7371 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7375 ERR(" OUT OF MEMORY!\n");
7376 return E_OUTOFMEMORY
;
7380 return TYPE_E_ELEMENTNOTFOUND
;
7383 /* ITypeInfo2::GetAllImplCustData
7385 * Gets all custom data items for the specified implementation type
7388 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
7391 CUSTDATA
*pCustData
)
7393 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7394 TLBCustData
*pCData
;
7395 TLBImplType
* pRDesc
;
7397 TRACE("(%p) index %d\n", This
, index
);
7398 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
7399 pRDesc
=pRDesc
->next
)
7402 pCustData
->prgCustData
=
7403 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
7404 if(pCustData
->prgCustData
){
7405 pCustData
->cCustData
=pRDesc
->ctCustData
;
7406 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
7407 pCData
= pCData
->next
){
7408 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7409 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7413 ERR(" OUT OF MEMORY!\n");
7414 return E_OUTOFMEMORY
;
7418 return TYPE_E_ELEMENTNOTFOUND
;
7421 static const ITypeInfo2Vtbl tinfvt
=
7424 ITypeInfo_fnQueryInterface
,
7426 ITypeInfo_fnRelease
,
7428 ITypeInfo_fnGetTypeAttr
,
7429 ITypeInfo_fnGetTypeComp
,
7430 ITypeInfo_fnGetFuncDesc
,
7431 ITypeInfo_fnGetVarDesc
,
7432 ITypeInfo_fnGetNames
,
7433 ITypeInfo_fnGetRefTypeOfImplType
,
7434 ITypeInfo_fnGetImplTypeFlags
,
7435 ITypeInfo_fnGetIDsOfNames
,
7437 ITypeInfo_fnGetDocumentation
,
7438 ITypeInfo_fnGetDllEntry
,
7439 ITypeInfo_fnGetRefTypeInfo
,
7440 ITypeInfo_fnAddressOfMember
,
7441 ITypeInfo_fnCreateInstance
,
7442 ITypeInfo_fnGetMops
,
7443 ITypeInfo_fnGetContainingTypeLib
,
7444 ITypeInfo_fnReleaseTypeAttr
,
7445 ITypeInfo_fnReleaseFuncDesc
,
7446 ITypeInfo_fnReleaseVarDesc
,
7448 ITypeInfo2_fnGetTypeKind
,
7449 ITypeInfo2_fnGetTypeFlags
,
7450 ITypeInfo2_fnGetFuncIndexOfMemId
,
7451 ITypeInfo2_fnGetVarIndexOfMemId
,
7452 ITypeInfo2_fnGetCustData
,
7453 ITypeInfo2_fnGetFuncCustData
,
7454 ITypeInfo2_fnGetParamCustData
,
7455 ITypeInfo2_fnGetVarCustData
,
7456 ITypeInfo2_fnGetImplTypeCustData
,
7457 ITypeInfo2_fnGetDocumentation2
,
7458 ITypeInfo2_fnGetAllCustData
,
7459 ITypeInfo2_fnGetAllFuncCustData
,
7460 ITypeInfo2_fnGetAllParamCustData
,
7461 ITypeInfo2_fnGetAllVarCustData
,
7462 ITypeInfo2_fnGetAllImplTypeCustData
,
7465 /******************************************************************************
7466 * CreateDispTypeInfo [OLEAUT32.31]
7468 * Build type information for an object so it can be called through an
7469 * IDispatch interface.
7472 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7473 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7476 * This call allows an objects methods to be accessed through IDispatch, by
7477 * building an ITypeInfo object that IDispatch can use to call through.
7479 HRESULT WINAPI
CreateDispTypeInfo(
7480 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
7481 LCID lcid
, /* [I] Locale Id */
7482 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
7484 ITypeInfoImpl
*pTIClass
, *pTIIface
;
7485 ITypeLibImpl
*pTypeLibImpl
;
7486 unsigned int param
, func
;
7487 TLBFuncDesc
**ppFuncDesc
;
7491 pTypeLibImpl
= TypeLibImpl_Constructor();
7492 if (!pTypeLibImpl
) return E_FAIL
;
7494 pTIIface
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
7495 pTIIface
->pTypeLib
= pTypeLibImpl
;
7496 pTIIface
->index
= 0;
7497 pTIIface
->Name
= NULL
;
7498 pTIIface
->dwHelpContext
= -1;
7499 memset(&pTIIface
->TypeAttr
.guid
, 0, sizeof(GUID
));
7500 pTIIface
->TypeAttr
.lcid
= lcid
;
7501 pTIIface
->TypeAttr
.typekind
= TKIND_INTERFACE
;
7502 pTIIface
->TypeAttr
.wMajorVerNum
= 0;
7503 pTIIface
->TypeAttr
.wMinorVerNum
= 0;
7504 pTIIface
->TypeAttr
.cbAlignment
= 2;
7505 pTIIface
->TypeAttr
.cbSizeInstance
= -1;
7506 pTIIface
->TypeAttr
.cbSizeVft
= -1;
7507 pTIIface
->TypeAttr
.cFuncs
= 0;
7508 pTIIface
->TypeAttr
.cImplTypes
= 0;
7509 pTIIface
->TypeAttr
.cVars
= 0;
7510 pTIIface
->TypeAttr
.wTypeFlags
= 0;
7512 ppFuncDesc
= &pTIIface
->funclist
;
7513 for(func
= 0; func
< pidata
->cMembers
; func
++) {
7514 METHODDATA
*md
= pidata
->pmethdata
+ func
;
7515 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
7516 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
7517 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
7518 (*ppFuncDesc
)->funcdesc
.lprgscode
= NULL
;
7519 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_VIRTUAL
;
7520 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
7521 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
7522 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
7523 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
7524 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
7525 (*ppFuncDesc
)->funcdesc
.cScodes
= 0;
7526 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0;
7527 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
7528 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
7529 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
7530 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
7531 md
->cArgs
* sizeof(ELEMDESC
));
7532 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
7533 md
->cArgs
* sizeof(TLBParDesc
));
7534 for(param
= 0; param
< md
->cArgs
; param
++) {
7535 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
7536 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
7538 (*ppFuncDesc
)->helpcontext
= 0;
7539 (*ppFuncDesc
)->HelpStringContext
= 0;
7540 (*ppFuncDesc
)->HelpString
= NULL
;
7541 (*ppFuncDesc
)->Entry
= NULL
;
7542 (*ppFuncDesc
)->ctCustData
= 0;
7543 (*ppFuncDesc
)->pCustData
= NULL
;
7544 (*ppFuncDesc
)->next
= NULL
;
7545 pTIIface
->TypeAttr
.cFuncs
++;
7546 ppFuncDesc
= &(*ppFuncDesc
)->next
;
7549 dump_TypeInfo(pTIIface
);
7551 pTypeLibImpl
->pTypeInfo
= pTIIface
;
7552 pTypeLibImpl
->TypeInfoCount
++;
7554 pTIClass
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
7555 pTIClass
->pTypeLib
= pTypeLibImpl
;
7556 pTIClass
->index
= 1;
7557 pTIClass
->Name
= NULL
;
7558 pTIClass
->dwHelpContext
= -1;
7559 memset(&pTIClass
->TypeAttr
.guid
, 0, sizeof(GUID
));
7560 pTIClass
->TypeAttr
.lcid
= lcid
;
7561 pTIClass
->TypeAttr
.typekind
= TKIND_COCLASS
;
7562 pTIClass
->TypeAttr
.wMajorVerNum
= 0;
7563 pTIClass
->TypeAttr
.wMinorVerNum
= 0;
7564 pTIClass
->TypeAttr
.cbAlignment
= 2;
7565 pTIClass
->TypeAttr
.cbSizeInstance
= -1;
7566 pTIClass
->TypeAttr
.cbSizeVft
= -1;
7567 pTIClass
->TypeAttr
.cFuncs
= 0;
7568 pTIClass
->TypeAttr
.cImplTypes
= 1;
7569 pTIClass
->TypeAttr
.cVars
= 0;
7570 pTIClass
->TypeAttr
.wTypeFlags
= 0;
7572 pTIClass
->impltypelist
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pTIClass
->impltypelist
));
7573 pTIClass
->impltypelist
->hRef
= 0;
7575 ref
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref
));
7578 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
7579 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
7581 dump_TypeInfo(pTIClass
);
7583 pTIIface
->next
= pTIClass
;
7584 pTypeLibImpl
->TypeInfoCount
++;
7586 *pptinfo
= (ITypeInfo
*)pTIClass
;
7588 ITypeInfo_AddRef(*pptinfo
);
7589 ITypeLib_Release((ITypeLib
*)&pTypeLibImpl
->lpVtbl
);
7595 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
7597 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7599 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
7602 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
7604 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7606 return ITypeInfo_AddRef((ITypeInfo
*)This
);
7609 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
7611 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7613 return ITypeInfo_Release((ITypeInfo
*)This
);
7616 static HRESULT WINAPI
ITypeComp_fnBind(
7621 ITypeInfo
** ppTInfo
,
7622 DESCKIND
* pDescKind
,
7625 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7626 const TLBFuncDesc
*pFDesc
;
7627 const TLBVarDesc
*pVDesc
;
7628 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
7630 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7632 *pDescKind
= DESCKIND_NONE
;
7633 pBindPtr
->lpfuncdesc
= NULL
;
7636 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
7637 if (!strcmpiW(pFDesc
->Name
, szName
)) {
7638 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
7641 /* name found, but wrong flags */
7642 hr
= TYPE_E_TYPEMISMATCH
;
7647 HRESULT hr
= TLB_AllocAndInitFuncDesc(
7649 &pBindPtr
->lpfuncdesc
,
7650 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
7653 *pDescKind
= DESCKIND_FUNCDESC
;
7654 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7655 ITypeInfo_AddRef(*ppTInfo
);
7658 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
7659 if (!strcmpiW(pVDesc
->Name
, szName
)) {
7660 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
7663 *pDescKind
= DESCKIND_VARDESC
;
7664 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7665 ITypeInfo_AddRef(*ppTInfo
);
7670 /* FIXME: search each inherited interface, not just the first */
7671 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypelist
) {
7672 /* recursive search */
7676 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
7679 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
7680 ITypeInfo_Release(pTInfo
);
7684 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7685 ITypeComp_Release(pTComp
);
7688 WARN("Could not search inherited interface!\n");
7690 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
7694 static HRESULT WINAPI
ITypeComp_fnBindType(
7698 ITypeInfo
** ppTInfo
,
7699 ITypeComp
** ppTComp
)
7701 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
7703 /* strange behaviour (does nothing) but like the
7706 if (!ppTInfo
|| !ppTComp
)
7715 static const ITypeCompVtbl tcompvt
=
7718 ITypeComp_fnQueryInterface
,
7720 ITypeComp_fnRelease
,
7723 ITypeComp_fnBindType