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 (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
559 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
560 (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 /* Register all dispinterfaces (which includes dual interfaces) and
695 oleautomation interfaces */
696 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
697 kind
== TKIND_DISPATCH
)
699 /* register interface<->typelib coupling */
700 get_interface_key( &tattr
->guid
, keyName
);
701 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
702 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
705 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
706 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
708 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
709 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
710 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
711 (const BYTE
*)PSOA
, sizeof PSOA
);
715 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
716 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
717 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
718 (const BYTE
*)PSOA
, sizeof PSOA
);
722 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
723 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
726 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
727 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
729 StringFromGUID2(&attr
->guid
, buffer
, 40);
730 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
731 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
732 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
733 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
734 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
742 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
745 ITypeInfo_Release(tinfo
);
752 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
758 /******************************************************************************
759 * UnRegisterTypeLib [OLEAUT32.186]
760 * Removes information about a type library from the System Registry
767 HRESULT WINAPI
UnRegisterTypeLib(
768 REFGUID libid
, /* [in] Guid of the library */
769 WORD wVerMajor
, /* [in] major version */
770 WORD wVerMinor
, /* [in] minor version */
771 LCID lcid
, /* [in] locale id */
774 BSTR tlibPath
= NULL
;
777 WCHAR subKeyName
[50];
780 BOOL deleteOtherStuff
;
783 TYPEATTR
* typeAttr
= NULL
;
785 ITypeInfo
* typeInfo
= NULL
;
786 ITypeLib
* typeLib
= NULL
;
789 TRACE("(IID: %s)\n",debugstr_guid(libid
));
791 /* Create the path to the key */
792 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
794 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
796 TRACE("Unsupported syskind %i\n", syskind
);
797 result
= E_INVALIDARG
;
801 /* get the path to the typelib on disk */
802 if (QueryPathOfRegTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, &tlibPath
) != S_OK
) {
803 result
= E_INVALIDARG
;
807 /* Try and open the key to the type library. */
808 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
809 result
= E_INVALIDARG
;
813 /* Try and load the type library */
814 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
)) {
815 result
= TYPE_E_INVALIDSTATE
;
819 /* remove any types registered with this typelib */
820 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
821 for (i
=0; i
<numTypes
; i
++) {
822 /* get the kind of type */
823 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
827 /* skip non-interfaces, and get type info for the type */
828 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
831 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
834 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
838 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
839 kind
== TKIND_DISPATCH
)
841 /* the path to the type */
842 get_interface_key( &typeAttr
->guid
, subKeyName
);
844 /* Delete its bits */
845 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != ERROR_SUCCESS
)
848 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
849 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
850 RegDeleteKeyW(subKey
, TypeLibW
);
853 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
857 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
859 if (typeInfo
) ITypeInfo_Release(typeInfo
);
863 /* Now, delete the type library path subkey */
864 get_lcid_subkey( lcid
, syskind
, subKeyName
);
865 RegDeleteKeyW(key
, subKeyName
);
866 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
867 RegDeleteKeyW(key
, subKeyName
);
869 /* check if there is anything besides the FLAGS/HELPDIR keys.
870 If there is, we don't delete them */
871 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
872 deleteOtherStuff
= TRUE
;
874 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
875 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
877 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
878 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
879 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
880 deleteOtherStuff
= FALSE
;
884 /* only delete the other parts of the key if we're absolutely sure */
885 if (deleteOtherStuff
) {
886 RegDeleteKeyW(key
, FLAGSW
);
887 RegDeleteKeyW(key
, HELPDIRW
);
891 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
892 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
893 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
897 SysFreeString(tlibPath
);
898 if (typeLib
) ITypeLib_Release(typeLib
);
899 if (subKey
) RegCloseKey(subKey
);
900 if (key
) RegCloseKey(key
);
904 /*======================= ITypeLib implementation =======================*/
906 typedef struct tagTLBCustData
910 struct tagTLBCustData
* next
;
913 /* data structure for import typelibs */
914 typedef struct tagTLBImpLib
916 int offset
; /* offset in the file (MSFT)
917 offset in nametable (SLTG)
918 just used to identify library while reading
920 GUID guid
; /* libid */
921 BSTR name
; /* name */
923 LCID lcid
; /* lcid of imported typelib */
925 WORD wVersionMajor
; /* major version number */
926 WORD wVersionMinor
; /* minor version number */
928 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
929 NULL if not yet loaded */
930 struct tagTLBImpLib
* next
;
933 /* internal ITypeLib data */
934 typedef struct tagITypeLibImpl
936 const ITypeLib2Vtbl
*lpVtbl
;
937 const ITypeCompVtbl
*lpVtblTypeComp
;
939 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
942 /* strings can be stored in tlb as multibyte strings BUT they are *always*
943 * exported to the application as a UNICODE string.
950 int TypeInfoCount
; /* nr of typeinfo's in librarry */
951 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
952 int ctCustData
; /* number of items in cust data list */
953 TLBCustData
* pCustData
; /* linked list to cust data */
954 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
955 int ctTypeDesc
; /* number of items in type desc array */
956 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
957 library. Only used while reading MSFT
959 struct list ref_list
; /* list of ref types in this typelib */
960 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
963 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
964 struct tagITypeLibImpl
*next
, *prev
;
969 static const ITypeLib2Vtbl tlbvt
;
970 static const ITypeCompVtbl tlbtcvt
;
972 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
974 return (ITypeLibImpl
*)((char*)iface
- FIELD_OFFSET(ITypeLibImpl
, lpVtblTypeComp
));
977 /* ITypeLib methods */
978 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
979 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
981 /*======================= ITypeInfo implementation =======================*/
983 /* data for referenced types */
984 typedef struct tagTLBRefType
986 INT index
; /* Type index for internal ref or for external ref
987 it the format is SLTG. -2 indicates to
990 GUID guid
; /* guid of the referenced type */
991 /* if index == TLB_REF_USE_GUID */
993 HREFTYPE reference
; /* The href of this ref */
994 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
995 TLB_REF_INTERNAL for internal refs
996 TLB_REF_NOT_FOUND for broken refs */
1001 #define TLB_REF_USE_GUID -2
1003 #define TLB_REF_INTERNAL (void*)-2
1004 #define TLB_REF_NOT_FOUND (void*)-1
1006 /* internal Parameter data */
1007 typedef struct tagTLBParDesc
1011 TLBCustData
* pCustData
; /* linked list to cust data */
1014 /* internal Function data */
1015 typedef struct tagTLBFuncDesc
1017 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1018 BSTR Name
; /* the name of this function */
1019 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1021 int HelpStringContext
;
1023 BSTR Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1025 TLBCustData
* pCustData
; /* linked list to cust data; */
1026 struct tagTLBFuncDesc
* next
;
1029 /* internal Variable data */
1030 typedef struct tagTLBVarDesc
1032 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1033 BSTR Name
; /* the name of this variable */
1035 int HelpStringContext
; /* FIXME: where? */
1038 TLBCustData
* pCustData
;/* linked list to cust data; */
1039 struct tagTLBVarDesc
* next
;
1042 /* internal implemented interface data */
1043 typedef struct tagTLBImplType
1045 HREFTYPE hRef
; /* hRef of interface */
1046 int implflags
; /* IMPLFLAG_*s */
1048 TLBCustData
* pCustData
;/* linked list to custom data; */
1049 struct tagTLBImplType
*next
;
1052 /* internal TypeInfo data */
1053 typedef struct tagITypeInfoImpl
1055 const ITypeInfo2Vtbl
*lpVtbl
;
1056 const ITypeCompVtbl
*lpVtblTypeComp
;
1058 BOOL not_attached_to_typelib
;
1059 TYPEATTR TypeAttr
; /* _lots_ of type information. */
1060 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1061 int index
; /* index in this typelib; */
1062 HREFTYPE hreftype
; /* hreftype for app object binding */
1063 /* type libs seem to store the doc strings in ascii
1064 * so why should we do it in unicode?
1069 DWORD dwHelpContext
;
1070 DWORD dwHelpStringContext
;
1073 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
1076 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
1078 /* Implemented Interfaces */
1079 TLBImplType
* impltypelist
;
1082 TLBCustData
* pCustData
; /* linked list to cust data; */
1083 struct tagITypeInfoImpl
* next
;
1086 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1088 return (ITypeInfoImpl
*)((char*)iface
- FIELD_OFFSET(ITypeInfoImpl
, lpVtblTypeComp
));
1091 static const ITypeInfo2Vtbl tinfvt
;
1092 static const ITypeCompVtbl tcompvt
;
1094 static ITypeInfo2
* ITypeInfo_Constructor(void);
1095 static void ITypeInfo_fnDestroy(ITypeInfoImpl
*This
);
1097 typedef struct tagTLBContext
1099 unsigned int oStart
; /* start of TLB in file */
1100 unsigned int pos
; /* current pos */
1101 unsigned int length
; /* total length */
1102 void *mapping
; /* memory mapping */
1103 MSFT_SegDir
* pTblDir
;
1104 ITypeLibImpl
* pLibInfo
;
1108 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
, int offset
);
1113 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1114 if (pTD
->vt
& VT_RESERVED
)
1115 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1116 if (pTD
->vt
& VT_BYREF
)
1117 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1118 if (pTD
->vt
& VT_ARRAY
)
1119 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1120 if (pTD
->vt
& VT_VECTOR
)
1121 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1122 switch(pTD
->vt
& VT_TYPEMASK
) {
1123 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1124 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1125 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1126 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1127 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1128 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1129 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1130 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1131 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1132 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1133 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1134 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1135 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1136 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1137 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1138 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1139 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1140 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1141 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1142 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1143 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1144 pTD
->u
.hreftype
); break;
1145 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1146 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1147 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1148 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1150 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1151 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1153 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1154 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1155 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1158 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1162 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1164 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1165 dump_TypeDesc(&edesc
->tdesc
,buf
);
1166 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1167 MESSAGE("\t\tu.paramdesc.wParamFlags");
1168 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1169 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1170 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1171 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1172 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1173 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1174 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1175 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1176 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1178 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1180 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1181 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1182 MESSAGE("Param %d:\n",i
);
1183 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1185 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1186 switch (funcdesc
->funckind
) {
1187 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1188 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1189 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1190 case FUNC_STATIC
: MESSAGE("static");break;
1191 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1192 default: MESSAGE("unknown");break;
1194 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1195 switch (funcdesc
->invkind
) {
1196 case INVOKE_FUNC
: MESSAGE("func");break;
1197 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1198 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1199 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1201 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1202 switch (funcdesc
->callconv
) {
1203 case CC_CDECL
: MESSAGE("cdecl");break;
1204 case CC_PASCAL
: MESSAGE("pascal");break;
1205 case CC_STDCALL
: MESSAGE("stdcall");break;
1206 case CC_SYSCALL
: MESSAGE("syscall");break;
1209 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1210 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1211 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1213 MESSAGE("\telemdescFunc (return value type):\n");
1214 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1217 static const char * const typekind_desc
[] =
1230 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1233 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1234 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1235 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1238 dump_FUNCDESC(&(pfd
->funcdesc
));
1240 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1241 MESSAGE("\tentry: %s\n", (pfd
->Entry
== (void *)-1) ? "invalid" : debugstr_w(pfd
->Entry
));
1243 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
)
1247 dump_TLBFuncDescOne(pfd
);
1251 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
)
1255 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1260 static void dump_TLBImpLib(const TLBImpLib
*import
)
1262 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1263 debugstr_w(import
->name
));
1264 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1265 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1268 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1272 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1274 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1275 if(ref
->index
== -1)
1276 TRACE_(typelib
)("%s\n", debugstr_guid(&(ref
->guid
)));
1278 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1280 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1282 TRACE_(typelib
)("in lib\n");
1283 dump_TLBImpLib(ref
->pImpTLInfo
);
1288 static void dump_TLBImplType(const TLBImplType
* impl
)
1292 "implementing/inheriting interface hRef = %x implflags %x\n",
1293 impl
->hRef
, impl
->implflags
);
1298 static void dump_Variant(const VARIANT
* pvar
)
1302 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1306 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1307 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1309 TRACE(",%p", V_BYREF(pvar
));
1311 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1313 TRACE(",%p", V_ARRAY(pvar
));
1315 else switch (V_TYPE(pvar
))
1317 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1318 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1319 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1320 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1322 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1324 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1325 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1326 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1327 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1328 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1329 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1330 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1331 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1332 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1333 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1334 V_CY(pvar
).s
.Lo
); break;
1336 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1337 TRACE(",<invalid>");
1339 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1340 st
.wHour
, st
.wMinute
, st
.wSecond
);
1344 case VT_USERDEFINED
:
1346 case VT_NULL
: break;
1347 default: TRACE(",?"); break;
1353 static void dump_DispParms(const DISPPARAMS
* pdp
)
1357 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1359 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1361 TRACE("named args:\n");
1362 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1363 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1366 if (pdp
->cArgs
&& pdp
->rgvarg
)
1369 for (index
= 0; index
< pdp
->cArgs
; index
++)
1370 dump_Variant( &pdp
->rgvarg
[index
] );
1374 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1376 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1377 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1378 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1379 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1380 TRACE("fct:%u var:%u impl:%u\n",
1381 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1382 TRACE("wTypeFlags: 0x%04x\n", pty
->TypeAttr
.wTypeFlags
);
1383 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1384 if (pty
->TypeAttr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(pty
->DllName
));
1386 dump_TLBFuncDesc(pty
->funclist
);
1387 dump_TLBVarDesc(pty
->varlist
);
1388 dump_TLBImplType(pty
->impltypelist
);
1391 static void dump_VARDESC(const VARDESC
*v
)
1393 MESSAGE("memid %d\n",v
->memid
);
1394 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1395 MESSAGE("oInst %d\n",v
->u
.oInst
);
1396 dump_ELEMDESC(&(v
->elemdescVar
));
1397 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1398 MESSAGE("varkind %d\n",v
->varkind
);
1401 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1403 /* VT_LPWSTR is largest type that */
1404 /* may appear in type description*/
1405 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1406 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1407 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1408 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1409 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1410 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1414 static void TLB_abort(void)
1419 static void * TLB_Alloc(unsigned size
) __WINE_ALLOC_SIZE(1);
1420 static void * TLB_Alloc(unsigned size
)
1423 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1425 ERR("cannot allocate memory\n");
1430 static void TLB_Free(void * ptr
)
1432 HeapFree(GetProcessHeap(), 0, ptr
);
1435 /* returns the size required for a deep copy of a typedesc into a
1437 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1441 if (alloc_initial_space
)
1442 size
+= sizeof(TYPEDESC
);
1448 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1451 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1452 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1458 /* deep copy a typedesc into a flat buffer */
1459 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1464 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1473 dest
->u
.lptdesc
= buffer
;
1474 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1477 dest
->u
.lpadesc
= buffer
;
1478 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1479 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1480 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1486 /* free custom data allocated by MSFT_CustData */
1487 static inline void TLB_FreeCustData(TLBCustData
*pCustData
)
1489 TLBCustData
*pCustDataNext
;
1490 for (; pCustData
; pCustData
= pCustDataNext
)
1492 VariantClear(&pCustData
->data
);
1494 pCustDataNext
= pCustData
->next
;
1495 TLB_Free(pCustData
);
1499 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1504 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1505 ret
= SysAllocStringLen(NULL
, len
- 1);
1506 if (!ret
) return ret
;
1507 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1511 /**********************************************************************
1513 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1515 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
1520 static inline void MSFT_Seek(TLBContext
*pcx
, long where
)
1522 if (where
!= DO_NOT_SEEK
)
1524 where
+= pcx
->oStart
;
1525 if (where
> pcx
->length
)
1528 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1536 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1538 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1539 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1541 MSFT_Seek(pcx
, where
);
1542 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1543 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1548 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1553 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1554 FromLEDWords(buffer
, ret
);
1559 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1564 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1565 FromLEWords(buffer
, ret
);
1570 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1572 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1573 memset(pGuid
,0, sizeof(GUID
));
1576 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1577 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1578 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1579 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1580 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1583 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
1585 MSFT_NameIntro niName
;
1589 ERR_(typelib
)("bad offset %d\n", offset
);
1593 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1594 pcx
->pTblDir
->pNametab
.offset
+offset
);
1596 return niName
.hreftype
;
1599 static BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1602 MSFT_NameIntro niName
;
1604 BSTR bstrName
= NULL
;
1608 ERR_(typelib
)("bad offset %d\n", offset
);
1611 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1612 pcx
->pTblDir
->pNametab
.offset
+offset
);
1613 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1614 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1615 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1616 name
[niName
.namelen
& 0xff]='\0';
1618 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1621 /* no invalid characters in string */
1624 bstrName
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1626 /* don't check for invalid character since this has been done previously */
1627 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, bstrName
, lengthInChars
);
1631 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1635 static BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1642 if(offset
<0) return NULL
;
1643 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1644 if(length
<= 0) return 0;
1645 string
=TLB_Alloc(length
+1);
1646 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1647 string
[length
]='\0';
1649 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1650 string
, -1, NULL
, 0);
1652 /* no invalid characters in string */
1655 bstr
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1657 /* don't check for invalid character since this has been done previously */
1658 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, bstr
, lengthInChars
);
1662 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1666 * read a value and fill a VARIANT structure
1668 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1672 TRACE_(typelib
)("\n");
1674 if(offset
<0) { /* data are packed in here */
1675 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1676 V_I4(pVar
) = offset
& 0x3ffffff;
1679 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1680 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1681 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1682 switch (V_VT(pVar
)){
1683 case VT_EMPTY
: /* FIXME: is this right? */
1684 case VT_NULL
: /* FIXME: is this right? */
1685 case VT_I2
: /* this should not happen */
1696 case VT_VOID
: /* FIXME: is this right? */
1704 case VT_DECIMAL
: /* FIXME: is this right? */
1707 /* pointer types with known behaviour */
1710 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1713 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
1716 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
1718 nullPos
= MSFT_Tell(pcx
);
1719 size
= nullPos
- origPos
;
1720 MSFT_Seek(pcx
, origPos
);
1722 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1723 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1724 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1725 /* FIXME: do we need a AtoW conversion here? */
1726 V_UNION(pVar
, bstrVal
[size
])='\0';
1727 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1731 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1738 case VT_USERDEFINED
:
1744 case VT_STREAMED_OBJECT
:
1745 case VT_STORED_OBJECT
:
1746 case VT_BLOB_OBJECT
:
1751 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1755 if(size
>0) /* (big|small) endian correct? */
1756 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1760 * create a linked list with custom data
1762 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1768 TRACE_(typelib
)("\n");
1772 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1773 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1774 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1775 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1776 /* add new custom data at head of the list */
1777 pNew
->next
=*ppCustData
;
1779 offset
= entry
.next
;
1784 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1788 pTd
->vt
=type
& VT_TYPEMASK
;
1790 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1792 if(pTd
->vt
== VT_USERDEFINED
)
1793 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, pTd
->u
.hreftype
);
1795 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1798 static void MSFT_ResolveReferencedTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, TYPEDESC
*lpTypeDesc
)
1800 /* resolve referenced type if any */
1803 switch (lpTypeDesc
->vt
)
1806 lpTypeDesc
= lpTypeDesc
->u
.lptdesc
;
1810 lpTypeDesc
= & (lpTypeDesc
->u
.lpadesc
->tdescElem
);
1813 case VT_USERDEFINED
:
1814 MSFT_DoRefType(pcx
, pTI
->pTypeLib
,
1815 lpTypeDesc
->u
.hreftype
);
1827 MSFT_DoFuncs(TLBContext
* pcx
,
1832 TLBFuncDesc
** pptfd
)
1835 * member information is stored in a data structure at offset
1836 * indicated by the memoffset field of the typeinfo structure
1837 * There are several distinctive parts.
1838 * The first part starts with a field that holds the total length
1839 * of this (first) part excluding this field. Then follow the records,
1840 * for each member there is one record.
1842 * The first entry is always the length of the record (including this
1844 * The rest of the record depends on the type of the member. If there is
1845 * a field indicating the member type (function, variable, interface, etc)
1846 * I have not found it yet. At this time we depend on the information
1847 * in the type info and the usual order how things are stored.
1849 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1852 * Third is an equal sized array with file offsets to the name entry
1855 * The fourth and last (?) part is an array with offsets to the records
1856 * in the first part of this file segment.
1859 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1860 int recoffset
= offset
+ sizeof(INT
);
1862 char *recbuf
= HeapAlloc(GetProcessHeap(), 0, 0xffff);
1863 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1864 TLBFuncDesc
*ptfd_prev
= NULL
;
1866 TRACE_(typelib
)("\n");
1868 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1870 for ( i
= 0; i
< cFuncs
; i
++ )
1872 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1874 /* name, eventually add to a hash table */
1875 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1876 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1878 /* nameoffset is sometimes -1 on the second half of a propget/propput
1879 * pair of functions */
1880 if ((nameoffset
== -1) && (i
> 0))
1881 (*pptfd
)->Name
= SysAllocString(ptfd_prev
->Name
);
1883 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1885 /* read the function information record */
1886 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1888 reclength
&= 0xffff;
1890 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1892 /* do the attributes */
1893 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1896 if ( nrattributes
> 0 )
1898 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1900 if ( nrattributes
> 1 )
1902 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1903 pFuncRec
->OptAttr
[1]) ;
1905 if ( nrattributes
> 2 )
1907 if ( pFuncRec
->FKCCIC
& 0x2000 )
1909 if (!IS_INTRESOURCE(pFuncRec
->OptAttr
[2]))
1910 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->OptAttr
[2]);
1911 (*pptfd
)->Entry
= (BSTR
)pFuncRec
->OptAttr
[2];
1915 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1916 pFuncRec
->OptAttr
[2]);
1918 if( nrattributes
> 5 )
1920 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1922 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1925 pFuncRec
->OptAttr
[6],
1926 &(*pptfd
)->pCustData
);
1932 (*pptfd
)->Entry
= (BSTR
)-1;
1937 /* fill the FuncDesc Structure */
1938 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1939 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1941 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1942 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1943 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1944 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1945 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1946 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1947 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1951 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1953 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
);
1955 /* do the parameters/arguments */
1956 if(pFuncRec
->nrargs
)
1959 MSFT_ParameterInfo paraminfo
;
1961 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1962 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1964 (*pptfd
)->pParamDesc
=
1965 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1967 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1968 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1970 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1972 ELEMDESC
*elemdesc
= &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1979 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1982 if (paraminfo
.oName
== -1)
1983 /* this occurs for [propput] or [propget] methods, so
1984 * we should just set the name of the parameter to the
1985 * name of the method. */
1986 (*pptfd
)->pParamDesc
[j
].Name
= SysAllocString((*pptfd
)->Name
);
1988 (*pptfd
)->pParamDesc
[j
].Name
=
1989 MSFT_ReadName( pcx
, paraminfo
.oName
);
1990 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w((*pptfd
)->pParamDesc
[j
].Name
));
1992 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
1995 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
1996 (pFuncRec
->FKCCIC
& 0x1000) )
1998 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2000 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
2002 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2004 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
2005 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2007 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2011 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2013 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
2016 pFuncRec
->OptAttr
[7+j
],
2017 &(*pptfd
)->pParamDesc
[j
].pCustData
);
2020 /* SEEK value = jump to offset,
2021 * from there jump to the end of record,
2022 * go back by (j-1) arguments
2024 MSFT_ReadLEDWords( ¶minfo
,
2025 sizeof(MSFT_ParameterInfo
), pcx
,
2026 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2027 * sizeof(MSFT_ParameterInfo
)));
2031 /* scode is not used: archaic win16 stuff FIXME: right? */
2032 (*pptfd
)->funcdesc
.cScodes
= 0 ;
2033 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
2036 pptfd
= & ((*pptfd
)->next
);
2037 recoffset
+= reclength
;
2039 HeapFree(GetProcessHeap(), 0, recbuf
);
2042 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2043 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2045 int infolen
, nameoffset
, reclength
;
2047 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
2051 TRACE_(typelib
)("\n");
2053 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2054 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2055 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2056 recoffset
+= offset
+sizeof(INT
);
2057 for(i
=0;i
<cVars
;i
++){
2058 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
2059 /* name, eventually add to a hash table */
2060 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2061 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2062 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
2063 /* read the variable information record */
2064 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
2066 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
2068 if(reclength
>(6*sizeof(INT
)) )
2069 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
2070 if(reclength
>(7*sizeof(INT
)) )
2071 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
2072 if(reclength
>(8*sizeof(INT
)) )
2073 if(reclength
>(9*sizeof(INT
)) )
2074 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
2075 /* fill the VarDesc Structure */
2076 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
2077 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2078 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
2079 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
2080 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2081 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
2082 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2083 if(pVarRec
->VarKind
== VAR_CONST
){
2084 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
2085 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
2086 pVarRec
->OffsValue
, pcx
);
2088 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2089 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptvd
)->vardesc
.elemdescVar
.tdesc
);
2090 pptvd
=&((*pptvd
)->next
);
2091 recoffset
+= reclength
;
2094 /* fill in data for a hreftype (offset). When the referenced type is contained
2095 * in the typelib, it's just an (file) offset in the type info base dir.
2096 * If comes from import, it's an offset+1 in the ImpInfo table
2098 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
,
2103 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2105 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
2107 if(ref
->reference
== offset
) return;
2110 ref
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref
));
2111 list_add_tail(&pTL
->ref_list
, &ref
->entry
);
2113 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2114 /* external typelib */
2115 MSFT_ImpInfo impinfo
;
2116 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
2118 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2120 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2121 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2122 while (pImpLib
){ /* search the known offsets of all import libraries */
2123 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
2124 pImpLib
=pImpLib
->next
;
2127 ref
->reference
= offset
;
2128 ref
->pImpTLInfo
= pImpLib
;
2129 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2130 MSFT_ReadGuid(&ref
->guid
, impinfo
.oGuid
, pcx
);
2131 TRACE("importing by guid %s\n", debugstr_guid(&ref
->guid
));
2132 ref
->index
= TLB_REF_USE_GUID
;
2134 ref
->index
= impinfo
.oGuid
;
2136 ERR("Cannot find a reference\n");
2137 ref
->reference
= -1;
2138 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2141 /* in this typelib */
2142 ref
->index
= MSFT_HREFTYPE_INDEX(offset
);
2143 ref
->reference
= offset
;
2144 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
2148 /* process Implemented Interfaces of a com class */
2149 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2153 MSFT_RefRecord refrec
;
2154 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
2156 TRACE_(typelib
)("\n");
2158 for(i
=0;i
<count
;i
++){
2159 if(offset
<0) break; /* paranoia */
2160 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
2161 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2162 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, refrec
.reftype
);
2163 (*ppImpl
)->hRef
= refrec
.reftype
;
2164 (*ppImpl
)->implflags
=refrec
.flags
;
2165 (*ppImpl
)->ctCustData
=
2166 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
2167 offset
=refrec
.onext
;
2168 ppImpl
=&((*ppImpl
)->next
);
2172 * process a typeinfo record
2174 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2177 ITypeLibImpl
* pLibInfo
)
2179 MSFT_TypeInfoBase tiBase
;
2180 ITypeInfoImpl
*ptiRet
;
2182 TRACE_(typelib
)("count=%u\n", count
);
2184 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
2185 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2186 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2188 /* this is where we are coming from */
2189 ptiRet
->pTypeLib
= pLibInfo
;
2190 ptiRet
->index
=count
;
2191 /* fill in the typeattr fields */
2193 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2194 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2195 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2196 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2197 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2198 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2199 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2200 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2201 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2202 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2203 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2204 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2205 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2206 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2207 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2208 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2211 /* IDLDESC idldescType; *//* never saw this one != zero */
2213 /* name, eventually add to a hash table */
2214 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2215 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2216 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2218 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2219 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2220 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2222 if (ptiRet
->TypeAttr
.typekind
== TKIND_MODULE
)
2223 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2225 /* note: InfoType's Help file and HelpStringDll come from the containing
2226 * library. Further HelpString and Docstring appear to be the same thing :(
2229 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2230 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2231 ptiRet
->TypeAttr
.cVars
,
2232 tiBase
.memoffset
, & ptiRet
->funclist
);
2234 if(ptiRet
->TypeAttr
.cVars
>0 )
2235 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2236 ptiRet
->TypeAttr
.cVars
,
2237 tiBase
.memoffset
, & ptiRet
->varlist
);
2238 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2239 switch(ptiRet
->TypeAttr
.typekind
)
2242 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2245 case TKIND_DISPATCH
:
2246 /* This is not -1 when the interface is a non-base dual interface or
2247 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2248 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2252 if (tiBase
.datatype1
!= -1)
2254 ptiRet
->impltypelist
= TLB_Alloc(sizeof(TLBImplType
));
2255 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2256 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2260 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2261 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2262 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2267 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2269 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2270 debugstr_w(ptiRet
->Name
),
2271 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2272 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2273 if (TRACE_ON(typelib
))
2274 dump_TypeInfo(ptiRet
);
2279 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2280 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2281 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2284 static ITypeLibImpl
*tlb_cache_first
;
2285 static CRITICAL_SECTION cache_section
;
2286 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2288 0, 0, &cache_section
,
2289 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2290 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2292 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2295 typedef struct TLB_PEFile
2297 const IUnknownVtbl
*lpvtbl
;
2300 HRSRC typelib_resource
;
2301 HGLOBAL typelib_global
;
2302 LPVOID typelib_base
;
2305 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2307 if (IsEqualIID(riid
, &IID_IUnknown
))
2310 IUnknown_AddRef(iface
);
2314 return E_NOINTERFACE
;
2317 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2319 TLB_PEFile
*This
= (TLB_PEFile
*)iface
;
2320 return InterlockedIncrement(&This
->refs
);
2323 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2325 TLB_PEFile
*This
= (TLB_PEFile
*)iface
;
2326 ULONG refs
= InterlockedDecrement(&This
->refs
);
2329 if (This
->typelib_global
)
2330 FreeResource(This
->typelib_global
);
2332 FreeLibrary(This
->dll
);
2333 HeapFree(GetProcessHeap(), 0, This
);
2338 static const IUnknownVtbl TLB_PEFile_Vtable
=
2340 TLB_PEFile_QueryInterface
,
2345 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2349 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2351 return E_OUTOFMEMORY
;
2353 This
->lpvtbl
= &TLB_PEFile_Vtable
;
2356 This
->typelib_resource
= NULL
;
2357 This
->typelib_global
= NULL
;
2358 This
->typelib_base
= NULL
;
2360 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2361 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2365 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2366 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2367 if (This
->typelib_resource
)
2369 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2370 if (This
->typelib_global
)
2372 This
->typelib_base
= LockResource(This
->typelib_global
);
2374 if (This
->typelib_base
)
2376 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2377 *ppBase
= This
->typelib_base
;
2378 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2385 TLB_PEFile_Release((IUnknown
*)&This
->lpvtbl
);
2386 return TYPE_E_CANTLOADLIBRARY
;
2389 typedef struct TLB_NEFile
2391 const IUnknownVtbl
*lpvtbl
;
2393 LPVOID typelib_base
;
2396 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2398 if (IsEqualIID(riid
, &IID_IUnknown
))
2401 IUnknown_AddRef(iface
);
2405 return E_NOINTERFACE
;
2408 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2410 TLB_NEFile
*This
= (TLB_NEFile
*)iface
;
2411 return InterlockedIncrement(&This
->refs
);
2414 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2416 TLB_NEFile
*This
= (TLB_NEFile
*)iface
;
2417 ULONG refs
= InterlockedDecrement(&This
->refs
);
2420 HeapFree(GetProcessHeap(), 0, This
->typelib_base
);
2421 HeapFree(GetProcessHeap(), 0, This
);
2426 static const IUnknownVtbl TLB_NEFile_Vtable
=
2428 TLB_NEFile_QueryInterface
,
2433 /***********************************************************************
2434 * read_xx_header [internal]
2436 static int read_xx_header( HFILE lzfd
)
2438 IMAGE_DOS_HEADER mzh
;
2441 LZSeek( lzfd
, 0, SEEK_SET
);
2442 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
2444 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
2447 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2448 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
2451 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2453 if ( magic
[0] == 'N' && magic
[1] == 'E' )
2454 return IMAGE_OS2_SIGNATURE
;
2455 if ( magic
[0] == 'P' && magic
[1] == 'E' )
2456 return IMAGE_NT_SIGNATURE
;
2459 WARN("Can't handle %s files.\n", magic
);
2464 /***********************************************************************
2465 * find_ne_resource [internal]
2467 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
2468 DWORD
*resLen
, DWORD
*resOff
)
2470 IMAGE_OS2_HEADER nehd
;
2471 NE_TYPEINFO
*typeInfo
;
2472 NE_NAMEINFO
*nameInfo
;
2478 /* Read in NE header */
2479 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
2480 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
2482 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
2485 TRACE("No resources in NE dll\n" );
2489 /* Read in resource table */
2490 resTab
= HeapAlloc( GetProcessHeap(), 0, resTabSize
);
2491 if ( !resTab
) return FALSE
;
2493 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
2494 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
2496 HeapFree( GetProcessHeap(), 0, resTab
);
2501 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
2503 if (!IS_INTRESOURCE(typeid)) /* named type */
2505 BYTE len
= strlen( typeid );
2506 while (typeInfo
->type_id
)
2508 if (!(typeInfo
->type_id
& 0x8000))
2510 BYTE
*p
= resTab
+ typeInfo
->type_id
;
2511 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
2513 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2514 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2517 else /* numeric type id */
2519 WORD id
= LOWORD(typeid) | 0x8000;
2520 while (typeInfo
->type_id
)
2522 if (typeInfo
->type_id
== id
) goto found_type
;
2523 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2524 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2527 TRACE("No typeid entry found for %p\n", typeid );
2528 HeapFree( GetProcessHeap(), 0, resTab
);
2532 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
2534 if (!IS_INTRESOURCE(resid
)) /* named resource */
2536 BYTE len
= strlen( resid
);
2537 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2539 BYTE
*p
= resTab
+ nameInfo
->id
;
2540 if (nameInfo
->id
& 0x8000) continue;
2541 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
2544 else /* numeric resource id */
2546 WORD id
= LOWORD(resid
) | 0x8000;
2547 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2548 if (nameInfo
->id
== id
) goto found_name
;
2550 TRACE("No resid entry found for %p\n", typeid );
2551 HeapFree( GetProcessHeap(), 0, resTab
);
2555 /* Return resource data */
2556 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
2557 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
2559 HeapFree( GetProcessHeap(), 0, resTab
);
2563 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
2567 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2568 TLB_NEFile
*This
= NULL
;
2570 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2571 if (!This
) return E_OUTOFMEMORY
;
2573 This
->lpvtbl
= &TLB_NEFile_Vtable
;
2575 This
->typelib_base
= NULL
;
2577 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
2578 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
2580 DWORD reslen
, offset
;
2581 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
2583 This
->typelib_base
= HeapAlloc(GetProcessHeap(), 0, reslen
);
2584 if( !This
->typelib_base
)
2588 LZSeek( lzfd
, offset
, SEEK_SET
);
2589 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
2591 *ppBase
= This
->typelib_base
;
2592 *pdwTLBLength
= reslen
;
2593 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2599 if( lzfd
>= 0) LZClose( lzfd
);
2600 TLB_NEFile_Release((IUnknown
*)&This
->lpvtbl
);
2604 typedef struct TLB_Mapping
2606 const IUnknownVtbl
*lpvtbl
;
2610 LPVOID typelib_base
;
2613 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2615 if (IsEqualIID(riid
, &IID_IUnknown
))
2618 IUnknown_AddRef(iface
);
2622 return E_NOINTERFACE
;
2625 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
2627 TLB_Mapping
*This
= (TLB_Mapping
*)iface
;
2628 return InterlockedIncrement(&This
->refs
);
2631 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
2633 TLB_Mapping
*This
= (TLB_Mapping
*)iface
;
2634 ULONG refs
= InterlockedDecrement(&This
->refs
);
2637 if (This
->typelib_base
)
2638 UnmapViewOfFile(This
->typelib_base
);
2640 CloseHandle(This
->mapping
);
2641 if (This
->file
!= INVALID_HANDLE_VALUE
)
2642 CloseHandle(This
->file
);
2643 HeapFree(GetProcessHeap(), 0, This
);
2648 static const IUnknownVtbl TLB_Mapping_Vtable
=
2650 TLB_Mapping_QueryInterface
,
2655 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2659 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2661 return E_OUTOFMEMORY
;
2663 This
->lpvtbl
= &TLB_Mapping_Vtable
;
2665 This
->file
= INVALID_HANDLE_VALUE
;
2666 This
->mapping
= NULL
;
2667 This
->typelib_base
= NULL
;
2669 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
2670 if (INVALID_HANDLE_VALUE
!= This
->file
)
2672 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2675 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
2676 if(This
->typelib_base
)
2678 /* retrieve file size */
2679 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
2680 *ppBase
= This
->typelib_base
;
2681 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2687 IUnknown_Release((IUnknown
*)&This
->lpvtbl
);
2688 return TYPE_E_CANTLOADLIBRARY
;
2691 /****************************************************************************
2694 * find the type of the typelib file and map the typelib resource into
2697 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2698 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2699 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
2701 ITypeLibImpl
*entry
;
2704 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
2705 LPVOID pBase
= NULL
;
2706 DWORD dwTLBLength
= 0;
2707 IUnknown
*pFile
= NULL
;
2711 index_str
= strrchrW(pszFileName
, '\\');
2712 if(index_str
&& *++index_str
!= '\0')
2715 long idx
= strtolW(index_str
, &end_ptr
, 10);
2716 if(*end_ptr
== '\0')
2718 int str_len
= index_str
- pszFileName
- 1;
2720 file
= HeapAlloc(GetProcessHeap(), 0, (str_len
+ 1) * sizeof(WCHAR
));
2721 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
2726 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
2728 if(strchrW(file
, '\\'))
2730 lstrcpyW(pszPath
, file
);
2734 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
2735 pszPath
[len
] = '\\';
2736 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
2740 if(file
!= pszFileName
) HeapFree(GetProcessHeap(), 0, file
);
2742 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
2744 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2745 EnterCriticalSection(&cache_section
);
2746 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2748 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
2750 TRACE("cache hit\n");
2751 *ppTypeLib
= (ITypeLib2
*)entry
;
2752 ITypeLib_AddRef(*ppTypeLib
);
2753 LeaveCriticalSection(&cache_section
);
2757 LeaveCriticalSection(&cache_section
);
2759 /* now actually load and parse the typelib */
2761 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2762 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2763 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2764 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2765 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
2768 if (dwTLBLength
>= 4)
2770 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2771 if (dwSignature
== MSFT_SIGNATURE
)
2772 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2773 else if (dwSignature
== SLTG_SIGNATURE
)
2774 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2777 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
2778 ret
= TYPE_E_CANTLOADLIBRARY
;
2782 ret
= TYPE_E_CANTLOADLIBRARY
;
2783 IUnknown_Release(pFile
);
2787 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2789 TRACE("adding to cache\n");
2790 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath
)+1) * sizeof(WCHAR
));
2791 lstrcpyW(impl
->path
, pszPath
);
2792 /* We should really canonicalise the path here. */
2793 impl
->index
= index
;
2795 /* FIXME: check if it has added already in the meantime */
2796 EnterCriticalSection(&cache_section
);
2797 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2799 tlb_cache_first
= impl
;
2800 LeaveCriticalSection(&cache_section
);
2803 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
2808 /*================== ITypeLib(2) Methods ===================================*/
2810 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
2812 ITypeLibImpl
* pTypeLibImpl
;
2814 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2815 if (!pTypeLibImpl
) return NULL
;
2817 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2818 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2819 pTypeLibImpl
->ref
= 1;
2821 list_init(&pTypeLibImpl
->ref_list
);
2822 pTypeLibImpl
->dispatch_href
= -1;
2824 return pTypeLibImpl
;
2827 /****************************************************************************
2828 * ITypeLib2_Constructor_MSFT
2830 * loading an MSFT typelib from an in-memory image
2832 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2836 MSFT_Header tlbHeader
;
2837 MSFT_SegDir tlbSegDir
;
2838 ITypeLibImpl
* pTypeLibImpl
;
2840 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
2842 pTypeLibImpl
= TypeLibImpl_Constructor();
2843 if (!pTypeLibImpl
) return NULL
;
2845 /* get pointer to beginning of typelib data */
2849 cx
.pLibInfo
= pTypeLibImpl
;
2850 cx
.length
= dwTLBLength
;
2853 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2854 TRACE_(typelib
)("header:\n");
2855 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2856 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2857 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2860 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
2862 /* there is a small amount of information here until the next important
2864 * the segment directory . Try to calculate the amount of data */
2865 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2867 /* now read the segment directory */
2868 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2869 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2870 cx
.pTblDir
= &tlbSegDir
;
2872 /* just check two entries */
2873 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2875 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2876 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2880 /* now fill our internal data */
2881 /* TLIBATTR fields */
2882 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2884 pTypeLibImpl
->LibAttr
.lcid
= tlbHeader
.lcid2
;
2885 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2886 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2887 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2888 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2890 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
2892 /* name, eventually add to a hash table */
2893 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2896 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2897 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2899 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2902 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2903 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2906 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2909 if(tlbHeader
.CustomDataOffset
>= 0)
2911 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2914 /* fill in type descriptions */
2915 if(tlbSegDir
.pTypdescTab
.length
> 0)
2917 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2919 pTypeLibImpl
->ctTypeDesc
= cTD
;
2920 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2921 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2924 /* FIXME: add several sanity checks here */
2925 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2926 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2928 /* FIXME: check safearray */
2930 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2932 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2934 else if(td
[0] == VT_CARRAY
)
2936 /* array descr table here */
2937 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2939 else if(td
[0] == VT_USERDEFINED
)
2941 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2943 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2946 /* second time around to fill the array subscript info */
2949 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2950 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2952 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2953 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2956 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2958 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
2960 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2962 for(j
= 0; j
<td
[2]; j
++)
2964 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2965 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2966 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2967 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2972 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2973 ERR("didn't find array description data\n");
2978 /* imported type libs */
2979 if(tlbSegDir
.pImpFiles
.offset
>0)
2981 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2982 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2985 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2989 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2990 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2991 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2993 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2994 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2995 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2996 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2999 name
= TLB_Alloc(size
+1);
3000 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3001 (*ppImpLib
)->name
= TLB_MultiByteToBSTR(name
);
3004 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
3005 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3007 ppImpLib
= &(*ppImpLib
)->next
;
3011 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3012 if(pTypeLibImpl
->dispatch_href
!= -1)
3013 MSFT_DoRefType(&cx
, pTypeLibImpl
, pTypeLibImpl
->dispatch_href
);
3016 if(tlbHeader
.nrtypeinfos
>= 0 )
3018 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3019 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
3022 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3024 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3026 ppTI
= &((*ppTI
)->next
);
3027 (pTypeLibImpl
->TypeInfoCount
)++;
3031 TRACE("(%p)\n", pTypeLibImpl
);
3032 return (ITypeLib2
*) pTypeLibImpl
;
3036 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3042 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3043 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3047 guid
->Data4
[0] = s
>> 8;
3048 guid
->Data4
[1] = s
& 0xff;
3051 for(i
= 0; i
< 6; i
++) {
3052 memcpy(b
, str
+ 24 + 2 * i
, 2);
3053 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3058 static WORD
SLTG_ReadString(const char *ptr
, BSTR
*pBstr
)
3064 bytelen
= *(const WORD
*)ptr
;
3065 if(bytelen
== 0xffff) return 2;
3066 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3067 *pBstr
= SysAllocStringLen(NULL
, len
);
3069 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, *pBstr
, len
);
3073 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3078 bytelen
= *(const WORD
*)ptr
;
3079 if(bytelen
== 0xffff) return 2;
3080 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
3081 memcpy(*str
, ptr
+ 2, bytelen
);
3082 (*str
)[bytelen
] = '\0';
3086 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3088 char *ptr
= pLibBlk
;
3091 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3092 FIXME("libblk magic = %04x\n", w
);
3097 if((w
= *(WORD
*)ptr
) != 0xffff) {
3098 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3103 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
3105 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
3107 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3110 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
3113 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3114 pTypeLibImpl
->lcid
= pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3116 pTypeLibImpl
->lcid
= pTypeLibImpl
->LibAttr
.lcid
= 0;
3119 ptr
+= 4; /* skip res12 */
3121 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
3124 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
3127 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
3130 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
3131 ptr
+= sizeof(GUID
);
3133 return ptr
- (char*)pLibBlk
;
3136 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3141 } sltg_ref_lookup_t
;
3143 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3144 HREFTYPE
*typelib_ref
)
3146 if(table
&& typeinfo_ref
< table
->num
)
3148 *typelib_ref
= table
->refs
[typeinfo_ref
];
3152 ERR_(typelib
)("Unable to find reference\n");
3157 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3162 if((*pType
& 0xe00) == 0xe00) {
3164 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3166 pTD
= pTD
->u
.lptdesc
;
3168 switch(*pType
& 0x3f) {
3171 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3173 pTD
= pTD
->u
.lptdesc
;
3176 case VT_USERDEFINED
:
3177 pTD
->vt
= VT_USERDEFINED
;
3178 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3184 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3187 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3189 pTD
->vt
= VT_CARRAY
;
3190 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3192 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3193 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3194 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3195 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3197 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3203 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3207 pTD
->vt
= VT_SAFEARRAY
;
3208 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3210 pTD
= pTD
->u
.lptdesc
;
3214 pTD
->vt
= *pType
& 0x3f;
3223 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3224 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3226 /* Handle [in/out] first */
3227 if((*pType
& 0xc000) == 0xc000)
3228 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3229 else if(*pType
& 0x8000)
3230 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3231 else if(*pType
& 0x4000)
3232 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3234 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3237 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3240 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3242 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3246 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3251 TLBRefType
*ref_type
;
3252 sltg_ref_lookup_t
*table
;
3253 HREFTYPE typelib_ref
;
3255 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3256 FIXME("Ref magic = %x\n", pRef
->magic
);
3259 name
= ( (char*)pRef
->names
+ pRef
->number
);
3261 table
= HeapAlloc(GetProcessHeap(), 0, sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3262 table
->num
= pRef
->number
>> 3;
3264 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3266 /* We don't want the first href to be 0 */
3267 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3269 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3271 unsigned int lib_offs
, type_num
;
3273 ref_type
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref_type
));
3275 name
+= SLTG_ReadStringA(name
, &refname
);
3276 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3277 FIXME_(typelib
)("Can't sscanf ref\n");
3278 if(lib_offs
!= 0xffff) {
3279 TLBImpLib
**import
= &pTL
->pImpLibs
;
3282 if((*import
)->offset
== lib_offs
)
3284 import
= &(*import
)->next
;
3287 char fname
[MAX_PATH
+1];
3290 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3292 (*import
)->offset
= lib_offs
;
3293 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
3295 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3296 &(*import
)->wVersionMajor
,
3297 &(*import
)->wVersionMinor
,
3298 &(*import
)->lcid
, fname
) != 4) {
3299 FIXME_(typelib
)("can't sscanf ref %s\n",
3300 pNameTable
+ lib_offs
+ 40);
3302 len
= strlen(fname
);
3303 if(fname
[len
-1] != '#')
3304 FIXME("fname = %s\n", fname
);
3305 fname
[len
-1] = '\0';
3306 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
3308 ref_type
->pImpTLInfo
= *import
;
3310 /* Store a reference to IDispatch */
3311 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&(*import
)->guid
, &IID_StdOle
) && type_num
== 4)
3312 pTL
->dispatch_href
= typelib_ref
;
3314 } else { /* internal ref */
3315 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3317 ref_type
->reference
= typelib_ref
;
3318 ref_type
->index
= type_num
;
3320 HeapFree(GetProcessHeap(), 0, refname
);
3321 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3323 table
->refs
[ref
] = typelib_ref
;
3326 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3327 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3328 dump_TLBRefType(pTL
);
3332 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3333 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3335 SLTG_ImplInfo
*info
;
3336 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
3337 /* I don't really get this structure, usually it's 0x16 bytes
3338 long, but iuser.tlb contains some that are 0x18 bytes long.
3339 That's ok because we can use the next ptr to jump to the next
3340 one. But how do we know the length of the last one? The WORD
3341 at offs 0x8 might be the clue. For now I'm just assuming that
3342 the last one is the regular 0x16 bytes. */
3344 info
= (SLTG_ImplInfo
*)pBlk
;
3346 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3347 sizeof(**ppImplType
));
3348 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &(*ppImplType
)->hRef
);
3349 (*ppImplType
)->implflags
= info
->impltypeflags
;
3350 pTI
->TypeAttr
.cImplTypes
++;
3351 ppImplType
= &(*ppImplType
)->next
;
3353 if(info
->next
== 0xffff)
3356 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3357 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3359 info
++; /* see comment at top of function */
3363 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
3364 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3366 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
3367 BSTR bstrPrevName
= NULL
;
3368 SLTG_Variable
*pItem
;
3372 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
3373 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++) {
3375 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3376 sizeof(**ppVarDesc
));
3377 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
3379 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
3380 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
3381 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
3385 if (pItem
->name
== 0xfffe)
3386 (*ppVarDesc
)->Name
= SysAllocString(bstrPrevName
);
3388 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3390 TRACE_(typelib
)("name: %s\n", debugstr_w((*ppVarDesc
)->Name
));
3391 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
3392 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
3394 if(pItem
->flags
& 0x02)
3395 pType
= &pItem
->type
;
3397 pType
= (WORD
*)(pBlk
+ pItem
->type
);
3399 if (pItem
->flags
& ~0xda)
3400 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
3402 SLTG_DoElem(pType
, pBlk
,
3403 &(*ppVarDesc
)->vardesc
.elemdescVar
, ref_lookup
);
3405 if (TRACE_ON(typelib
)) {
3407 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
3408 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
3411 if (pItem
->flags
& 0x40) {
3412 TRACE_(typelib
)("VAR_DISPATCH\n");
3413 (*ppVarDesc
)->vardesc
.varkind
= VAR_DISPATCH
;
3415 else if (pItem
->flags
& 0x10) {
3416 TRACE_(typelib
)("VAR_CONST\n");
3417 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
3418 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
3420 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
3421 if (pItem
->flags
& 0x08)
3422 V_INT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
3424 switch ((*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
)
3430 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
3432 TRACE_(typelib
)("len = %u\n", len
);
3433 if (len
== 0xffff) {
3436 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
3437 str
= SysAllocStringLen(NULL
, alloc_len
);
3438 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
3440 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_BSTR
;
3441 V_BSTR((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = str
;
3450 V_INT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) =
3451 *(INT
*)(pBlk
+ pItem
->byte_offs
);
3454 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
);
3459 TRACE_(typelib
)("VAR_PERINSTANCE\n");
3460 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
3461 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
3464 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
3465 (*ppVarDesc
)->vardesc
.wVarFlags
= pItem
->varflags
;
3467 if (pItem
->flags
& 0x80)
3468 (*ppVarDesc
)->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
3470 bstrPrevName
= (*ppVarDesc
)->Name
;
3471 ppVarDesc
= &((*ppVarDesc
)->next
);
3473 pTI
->TypeAttr
.cVars
= cVars
;
3476 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
3477 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3479 SLTG_Function
*pFunc
;
3481 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
3483 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
;
3484 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++) {
3489 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3490 sizeof(**ppFuncDesc
));
3492 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
3493 case SLTG_FUNCTION_MAGIC
:
3494 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
3496 case SLTG_DISPATCH_FUNCTION_MAGIC
:
3497 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_DISPATCH
;
3499 case SLTG_STATIC_FUNCTION_MAGIC
:
3500 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_STATIC
;
3503 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
3504 HeapFree(GetProcessHeap(), 0, *ppFuncDesc
);
3508 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
3510 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
3511 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
3512 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
3513 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
3514 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
3515 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
3517 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
3518 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
3520 if(pFunc
->retnextopt
& 0x80)
3521 pType
= &pFunc
->rettype
;
3523 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
3525 SLTG_DoElem(pType
, pBlk
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
, ref_lookup
);
3527 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
3528 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3529 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
3530 (*ppFuncDesc
)->pParamDesc
=
3531 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3532 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
3534 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
3536 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
3537 char *paramName
= pNameTable
+ *pArg
;
3539 /* If arg type follows then paramName points to the 2nd
3540 letter of the name, else the next WORD is an offset to
3541 the arg type and paramName points to the first letter.
3542 So let's take one char off paramName and see if we're
3543 pointing at an alpha-numeric char. However if *pArg is
3544 0xffff or 0xfffe then the param has no name, the former
3545 meaning that the next WORD is the type, the latter
3546 meaning that the next WORD is an offset to the type. */
3551 else if(*pArg
== 0xfffe) {
3555 else if(paramName
[-1] && !isalnum(paramName
[-1]))
3560 if(HaveOffs
) { /* the next word is an offset to type */
3561 pType
= (WORD
*)(pBlk
+ *pArg
);
3562 SLTG_DoElem(pType
, pBlk
,
3563 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3568 pArg
= SLTG_DoElem(pArg
, pBlk
,
3569 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3572 /* Are we an optional param ? */
3573 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
3574 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
3575 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
3578 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
3579 TLB_MultiByteToBSTR(paramName
);
3581 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
3582 SysAllocString((*ppFuncDesc
)->Name
);
3586 ppFuncDesc
= &((*ppFuncDesc
)->next
);
3587 if(pFunc
->next
== 0xffff) break;
3589 pTI
->TypeAttr
.cFuncs
= cFuncs
;
3592 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
3593 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3594 SLTG_TypeInfoTail
*pTITail
)
3597 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3599 if(pTIHeader
->href_table
!= 0xffffffff) {
3600 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3606 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3607 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
3609 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3613 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
3614 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3615 const SLTG_TypeInfoTail
*pTITail
)
3618 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3620 if(pTIHeader
->href_table
!= 0xffffffff) {
3621 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3627 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3628 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
3631 if (pTITail
->funcs_off
!= 0xffff)
3632 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3634 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3636 if (TRACE_ON(typelib
))
3637 dump_TLBFuncDesc(pTI
->funclist
);
3640 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
3641 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3642 const SLTG_TypeInfoTail
*pTITail
)
3644 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3647 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3648 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3649 const SLTG_TypeInfoTail
*pTITail
)
3652 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3654 if (pTITail
->simple_alias
) {
3655 /* if simple alias, no more processing required */
3656 pTI
->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3660 if(pTIHeader
->href_table
!= 0xffffffff) {
3661 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3665 /* otherwise it is an offset to a type */
3666 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
3668 SLTG_DoType(pType
, pBlk
, &pTI
->TypeAttr
.tdescAlias
, ref_lookup
);
3670 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3673 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3674 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3675 const SLTG_TypeInfoTail
*pTITail
)
3677 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3678 if (pTIHeader
->href_table
!= 0xffffffff)
3679 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3682 if (pTITail
->vars_off
!= 0xffff)
3683 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3685 if (pTITail
->funcs_off
!= 0xffff)
3686 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3688 if (pTITail
->impls_off
!= 0xffff)
3689 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
3691 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3692 * of dispinterface functions including the IDispatch ones, so
3693 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3694 pTI
->TypeAttr
.cbSizeVft
= pTI
->TypeAttr
.cFuncs
* sizeof(void *);
3696 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3697 if (TRACE_ON(typelib
))
3698 dump_TLBFuncDesc(pTI
->funclist
);
3701 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3702 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3703 const SLTG_TypeInfoTail
*pTITail
)
3705 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3708 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
3709 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3710 const SLTG_TypeInfoTail
*pTITail
)
3712 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3713 if (pTIHeader
->href_table
!= 0xffffffff)
3714 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3717 if (pTITail
->vars_off
!= 0xffff)
3718 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3720 if (pTITail
->funcs_off
!= 0xffff)
3721 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3722 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3723 if (TRACE_ON(typelib
))
3727 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3728 managable copy of it into this */
3741 } SLTG_InternalOtherTypeInfo
;
3743 /****************************************************************************
3744 * ITypeLib2_Constructor_SLTG
3746 * loading a SLTG typelib from an in-memory image
3748 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3750 ITypeLibImpl
*pTypeLibImpl
;
3751 SLTG_Header
*pHeader
;
3752 SLTG_BlkEntry
*pBlkEntry
;
3756 LPVOID pBlk
, pFirstBlk
;
3757 SLTG_LibBlk
*pLibBlk
;
3758 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3759 char *pAfterOTIBlks
= NULL
;
3760 char *pNameTable
, *ptr
;
3763 ITypeInfoImpl
**ppTypeInfoImpl
;
3765 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3768 pTypeLibImpl
= TypeLibImpl_Constructor();
3769 if (!pTypeLibImpl
) return NULL
;
3773 TRACE_(typelib
)("header:\n");
3774 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
3775 pHeader
->nrOfFileBlks
);
3776 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3777 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
3778 pHeader
->SLTG_magic
);
3782 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3783 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3785 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3786 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3788 /* Next we have a magic block */
3789 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3791 /* Let's see if we're still in sync */
3792 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3793 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3794 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3797 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3798 sizeof(SLTG_DIR_MAGIC
))) {
3799 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
3803 pIndex
= (SLTG_Index
*)(pMagic
+1);
3805 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3807 pFirstBlk
= pPad9
+ 1;
3809 /* We'll set up a ptr to the main library block, which is the last one. */
3811 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3812 pBlkEntry
[order
].next
!= 0;
3813 order
= pBlkEntry
[order
].next
- 1, i
++) {
3814 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3818 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3820 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3825 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3827 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3828 sizeof(*pOtherTypeInfoBlks
) *
3829 pTypeLibImpl
->TypeInfoCount
);
3832 ptr
= (char*)pLibBlk
+ len
;
3834 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3838 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3840 w
= *(WORD
*)(ptr
+ 2);
3843 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3845 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3846 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3848 w
= *(WORD
*)(ptr
+ 4 + len
);
3850 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3852 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3854 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3855 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3857 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3858 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3859 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3861 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3863 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3866 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3867 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3868 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3869 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3870 len
+= sizeof(SLTG_OtherTypeInfo
);
3874 pAfterOTIBlks
= ptr
;
3876 /* Skip this WORD and get the next DWORD */
3877 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3879 /* Now add this to pLibBLk look at what we're pointing at and
3880 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3881 dust and we should be pointing at the beginning of the name
3884 pNameTable
= (char*)pLibBlk
+ len
;
3886 switch(*(WORD
*)pNameTable
) {
3893 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3897 pNameTable
+= 0x216;
3901 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3903 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3906 /* Hopefully we now have enough ptrs set up to actually read in
3907 some TypeInfos. It's not clear which order to do them in, so
3908 I'll just follow the links along the BlkEntry chain and read
3909 them in the order in which they are in the file */
3911 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3913 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3914 pBlkEntry
[order
].next
!= 0;
3915 order
= pBlkEntry
[order
].next
- 1, i
++) {
3917 SLTG_TypeInfoHeader
*pTIHeader
;
3918 SLTG_TypeInfoTail
*pTITail
;
3919 SLTG_MemberHeader
*pMemHeader
;
3921 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3922 pOtherTypeInfoBlks
[i
].index_name
)) {
3923 FIXME_(typelib
)("Index strings don't match\n");
3928 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3929 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3932 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3933 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3934 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
3936 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3937 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3938 (*ppTypeInfoImpl
)->index
= i
;
3939 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3940 pOtherTypeInfoBlks
[i
].name_offs
+
3942 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3943 (*ppTypeInfoImpl
)->TypeAttr
.guid
= pOtherTypeInfoBlks
[i
].uuid
;
3944 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3945 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3946 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3947 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3948 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3950 if((*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
3951 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= TKIND_DISPATCH
;
3953 if((pTIHeader
->typeflags1
& 7) != 2)
3954 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3955 if(pTIHeader
->typeflags3
!= 2)
3956 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3958 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3959 debugstr_w((*ppTypeInfoImpl
)->Name
),
3960 typekind_desc
[pTIHeader
->typekind
],
3961 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3962 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3964 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
3966 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
3968 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3969 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3970 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3972 switch(pTIHeader
->typekind
) {
3974 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3975 pTIHeader
, pTITail
);
3979 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3980 pTIHeader
, pTITail
);
3983 case TKIND_INTERFACE
:
3984 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3985 pTIHeader
, pTITail
);
3989 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3990 pTIHeader
, pTITail
);
3994 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3995 pTIHeader
, pTITail
);
3998 case TKIND_DISPATCH
:
3999 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4000 pTIHeader
, pTITail
);
4004 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4005 pTIHeader
, pTITail
);
4009 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4014 /* could get cFuncs, cVars and cImplTypes from here
4015 but we've already set those */
4016 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4031 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
4032 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4035 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4036 FIXME("Somehow processed %d TypeInfos\n", i
);
4040 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
4041 return (ITypeLib2
*)pTypeLibImpl
;
4044 /* ITypeLib::QueryInterface
4046 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
4051 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4053 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4056 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4057 IsEqualIID(riid
,&IID_ITypeLib
)||
4058 IsEqualIID(riid
,&IID_ITypeLib2
))
4065 ITypeLib2_AddRef(iface
);
4066 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4069 TRACE("-- Interface: E_NOINTERFACE\n");
4070 return E_NOINTERFACE
;
4075 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4077 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4078 ULONG ref
= InterlockedIncrement(&This
->ref
);
4080 TRACE("(%p)->ref was %u\n",This
, ref
- 1);
4085 /* ITypeLib::Release
4087 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4089 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4090 ULONG ref
= InterlockedDecrement(&This
->ref
);
4092 TRACE("(%p)->(%u)\n",This
, ref
);
4096 TLBImpLib
*pImpLib
, *pImpLibNext
;
4097 TLBCustData
*pCustData
, *pCustDataNext
;
4098 TLBRefType
*ref_type
;
4101 ITypeInfoImpl
*pTI
, *pTINext
;
4103 /* remove cache entry */
4106 TRACE("removing from cache list\n");
4107 EnterCriticalSection(&cache_section
);
4108 if (This
->next
) This
->next
->prev
= This
->prev
;
4109 if (This
->prev
) This
->prev
->next
= This
->next
;
4110 else tlb_cache_first
= This
->next
;
4111 LeaveCriticalSection(&cache_section
);
4112 HeapFree(GetProcessHeap(), 0, This
->path
);
4114 TRACE(" destroying ITypeLib(%p)\n",This
);
4116 SysFreeString(This
->Name
);
4119 SysFreeString(This
->DocString
);
4120 This
->DocString
= NULL
;
4122 SysFreeString(This
->HelpFile
);
4123 This
->HelpFile
= NULL
;
4125 SysFreeString(This
->HelpStringDll
);
4126 This
->HelpStringDll
= NULL
;
4128 for (pCustData
= This
->pCustData
; pCustData
; pCustData
= pCustDataNext
)
4130 VariantClear(&pCustData
->data
);
4132 pCustDataNext
= pCustData
->next
;
4133 TLB_Free(pCustData
);
4136 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4137 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4138 TLB_Free(This
->pTypeDesc
[i
].u
.lpadesc
);
4140 TLB_Free(This
->pTypeDesc
);
4142 for (pImpLib
= This
->pImpLibs
; pImpLib
; pImpLib
= pImpLibNext
)
4144 if (pImpLib
->pImpTypeLib
)
4145 ITypeLib_Release((ITypeLib
*)pImpLib
->pImpTypeLib
);
4146 SysFreeString(pImpLib
->name
);
4148 pImpLibNext
= pImpLib
->next
;
4152 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4154 list_remove(&ref_type
->entry
);
4158 for (pTI
= This
->pTypeInfo
; pTI
; pTI
= pTINext
)
4160 pTINext
= pTI
->next
;
4161 ITypeInfo_fnDestroy(pTI
);
4163 HeapFree(GetProcessHeap(),0,This
);
4170 /* ITypeLib::GetTypeInfoCount
4172 * Returns the number of type descriptions in the type library
4174 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4176 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4177 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4178 return This
->TypeInfoCount
;
4181 /* ITypeLib::GetTypeInfo
4183 * retrieves the specified type description in the library.
4185 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4188 ITypeInfo
**ppTInfo
)
4192 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4193 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
4195 TRACE("(%p)->(index=%d)\n", This
, index
);
4197 if (!ppTInfo
) return E_INVALIDARG
;
4199 /* search element n in list */
4200 for(i
=0; i
< index
; i
++)
4202 pTypeInfo
= pTypeInfo
->next
;
4205 TRACE("-- element not found\n");
4206 return TYPE_E_ELEMENTNOTFOUND
;
4210 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
4212 ITypeInfo_AddRef(*ppTInfo
);
4213 TRACE("-- found (%p)\n",*ppTInfo
);
4218 /* ITypeLibs::GetTypeInfoType
4220 * Retrieves the type of a type description.
4222 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4227 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4229 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
4231 if (ITypeLib2_fnGetTypeInfoCount(iface
) < index
+ 1)
4232 return TYPE_E_ELEMENTNOTFOUND
;
4234 TRACE("(%p) index %d\n", This
, index
);
4236 if(!pTKind
) return E_INVALIDARG
;
4238 /* search element n in list */
4239 for(i
=0; i
< index
; i
++)
4243 TRACE("-- element not found\n");
4244 return TYPE_E_ELEMENTNOTFOUND
;
4246 pTInfo
= pTInfo
->next
;
4249 *pTKind
= pTInfo
->TypeAttr
.typekind
;
4250 TRACE("-- found Type (%d)\n", *pTKind
);
4254 /* ITypeLib::GetTypeInfoOfGuid
4256 * Retrieves the type description that corresponds to the specified GUID.
4259 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4262 ITypeInfo
**ppTInfo
)
4264 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4265 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
4267 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
4271 WARN("-- element not found\n");
4272 return TYPE_E_ELEMENTNOTFOUND
;
4275 /* search linked list for guid */
4276 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
4278 pTypeInfo
= pTypeInfo
->next
;
4282 /* end of list reached */
4283 WARN("-- element not found\n");
4284 return TYPE_E_ELEMENTNOTFOUND
;
4288 TRACE("-- found (%p, %s)\n",
4290 debugstr_w(pTypeInfo
->Name
));
4292 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
4293 ITypeInfo_AddRef(*ppTInfo
);
4297 /* ITypeLib::GetLibAttr
4299 * Retrieves the structure that contains the library's attributes.
4302 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4304 LPTLIBATTR
*ppTLibAttr
)
4306 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4307 TRACE("(%p)\n",This
);
4308 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
4309 **ppTLibAttr
= This
->LibAttr
;
4313 /* ITypeLib::GetTypeComp
4315 * Enables a client compiler to bind to a library's types, variables,
4316 * constants, and global functions.
4319 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4321 ITypeComp
**ppTComp
)
4323 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4325 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4326 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4327 ITypeComp_AddRef(*ppTComp
);
4332 /* ITypeLib::GetDocumentation
4334 * Retrieves the library's documentation string, the complete Help file name
4335 * and path, and the context identifier for the library Help topic in the Help
4338 * On a successful return all non-null BSTR pointers will have been set,
4341 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4345 BSTR
*pBstrDocString
,
4346 DWORD
*pdwHelpContext
,
4347 BSTR
*pBstrHelpFile
)
4349 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4351 HRESULT result
= E_INVALIDARG
;
4356 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4358 pBstrName
, pBstrDocString
,
4359 pdwHelpContext
, pBstrHelpFile
);
4363 /* documentation for the typelib */
4368 if(!(*pBstrName
= SysAllocString(This
->Name
)))
4376 if (This
->DocString
)
4378 if(!(*pBstrDocString
= SysAllocString(This
->DocString
)))
4381 else if (This
->Name
)
4383 if(!(*pBstrDocString
= SysAllocString(This
->Name
)))
4387 *pBstrDocString
= NULL
;
4391 *pdwHelpContext
= This
->dwHelpContext
;
4397 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
)))
4401 *pBstrHelpFile
= NULL
;
4408 /* for a typeinfo */
4409 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4411 if(SUCCEEDED(result
))
4413 result
= ITypeInfo_GetDocumentation(pTInfo
,
4417 pdwHelpContext
, pBstrHelpFile
);
4419 ITypeInfo_Release(pTInfo
);
4424 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
4426 if (pBstrName
) SysFreeString (*pBstrName
);
4428 return STG_E_INSUFFICIENTMEMORY
;
4433 * Indicates whether a passed-in string contains the name of a type or member
4434 * described in the library.
4437 static HRESULT WINAPI
ITypeLib2_fnIsName(
4443 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4444 ITypeInfoImpl
*pTInfo
;
4445 TLBFuncDesc
*pFInfo
;
4448 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
4450 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
4454 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
4455 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4456 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
4457 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4458 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
4459 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
4460 goto ITypeLib2_fnIsName_exit
;
4462 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
4463 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4468 ITypeLib2_fnIsName_exit
:
4469 TRACE("(%p)slow! search for %s: %s found!\n", This
,
4470 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
4475 /* ITypeLib::FindName
4477 * Finds occurrences of a type description in a type library. This may be used
4478 * to quickly verify that a name exists in a type library.
4481 static HRESULT WINAPI
ITypeLib2_fnFindName(
4485 ITypeInfo
**ppTInfo
,
4489 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4490 ITypeInfoImpl
*pTInfo
;
4491 TLBFuncDesc
*pFInfo
;
4494 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
4496 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
4497 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4498 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
4499 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4500 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++) {
4501 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
4502 goto ITypeLib2_fnFindName_exit
;
4505 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
4506 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4508 ITypeLib2_fnFindName_exit
:
4509 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
4510 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
4513 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4514 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
4521 /* ITypeLib::ReleaseTLibAttr
4523 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4526 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
4528 TLIBATTR
*pTLibAttr
)
4530 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4531 TRACE("freeing (%p)\n",This
);
4532 HeapFree(GetProcessHeap(),0,pTLibAttr
);
4536 /* ITypeLib2::GetCustData
4538 * gets the custom data
4540 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
4545 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4546 TLBCustData
*pCData
;
4548 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
4550 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4553 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4557 VariantInit( pVarVal
);
4558 VariantCopy( pVarVal
, &pCData
->data
);
4561 return E_INVALIDARG
; /* FIXME: correct? */
4564 /* ITypeLib2::GetLibStatistics
4566 * Returns statistics about a type library that are required for efficient
4567 * sizing of hash tables.
4570 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
4572 ULONG
*pcUniqueNames
,
4573 ULONG
*pcchUniqueNames
)
4575 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4577 FIXME("(%p): stub!\n", This
);
4579 if(pcUniqueNames
) *pcUniqueNames
=1;
4580 if(pcchUniqueNames
) *pcchUniqueNames
=1;
4584 /* ITypeLib2::GetDocumentation2
4586 * Retrieves the library's documentation string, the complete Help file name
4587 * and path, the localization context to use, and the context ID for the
4588 * library Help topic in the Help file.
4591 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
4595 BSTR
*pbstrHelpString
,
4596 DWORD
*pdwHelpStringContext
,
4597 BSTR
*pbstrHelpStringDll
)
4599 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4603 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
4605 /* the help string should be obtained from the helpstringdll,
4606 * using the _DLLGetDocumentation function, based on the supplied
4607 * lcid. Nice to do sometime...
4611 /* documentation for the typelib */
4613 *pbstrHelpString
=SysAllocString(This
->DocString
);
4614 if(pdwHelpStringContext
)
4615 *pdwHelpStringContext
=This
->dwHelpContext
;
4616 if(pbstrHelpStringDll
)
4617 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
4623 /* for a typeinfo */
4624 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
4626 if(SUCCEEDED(result
))
4628 ITypeInfo2
* pTInfo2
;
4629 result
= ITypeInfo_QueryInterface(pTInfo
,
4631 (LPVOID
*) &pTInfo2
);
4633 if(SUCCEEDED(result
))
4635 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
4639 pdwHelpStringContext
,
4640 pbstrHelpStringDll
);
4642 ITypeInfo2_Release(pTInfo2
);
4645 ITypeInfo_Release(pTInfo
);
4651 /* ITypeLib2::GetAllCustData
4653 * Gets all custom data items for the library.
4656 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
4658 CUSTDATA
*pCustData
)
4660 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4661 TLBCustData
*pCData
;
4663 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
4664 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
4665 if(pCustData
->prgCustData
){
4666 pCustData
->cCustData
=This
->ctCustData
;
4667 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
4668 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4669 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
4672 ERR(" OUT OF MEMORY!\n");
4673 return E_OUTOFMEMORY
;
4678 static const ITypeLib2Vtbl tlbvt
= {
4679 ITypeLib2_fnQueryInterface
,
4681 ITypeLib2_fnRelease
,
4682 ITypeLib2_fnGetTypeInfoCount
,
4683 ITypeLib2_fnGetTypeInfo
,
4684 ITypeLib2_fnGetTypeInfoType
,
4685 ITypeLib2_fnGetTypeInfoOfGuid
,
4686 ITypeLib2_fnGetLibAttr
,
4687 ITypeLib2_fnGetTypeComp
,
4688 ITypeLib2_fnGetDocumentation
,
4690 ITypeLib2_fnFindName
,
4691 ITypeLib2_fnReleaseTLibAttr
,
4693 ITypeLib2_fnGetCustData
,
4694 ITypeLib2_fnGetLibStatistics
,
4695 ITypeLib2_fnGetDocumentation2
,
4696 ITypeLib2_fnGetAllCustData
4700 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4702 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4704 return ITypeLib2_QueryInterface((ITypeLib
*)This
, riid
, ppv
);
4707 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4709 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4711 return ITypeLib2_AddRef((ITypeLib2
*)This
);
4714 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4716 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4718 return ITypeLib2_Release((ITypeLib2
*)This
);
4721 static HRESULT WINAPI
ITypeLibComp_fnBind(
4726 ITypeInfo
** ppTInfo
,
4727 DESCKIND
* pDescKind
,
4730 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4731 ITypeInfoImpl
*pTypeInfo
;
4734 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4736 *pDescKind
= DESCKIND_NONE
;
4737 pBindPtr
->lptcomp
= NULL
;
4740 for (pTypeInfo
= This
->pTypeInfo
; pTypeInfo
; pTypeInfo
= pTypeInfo
->next
)
4742 TRACE("testing %s\n", debugstr_w(pTypeInfo
->Name
));
4744 /* FIXME: check wFlags here? */
4745 /* FIXME: we should use a hash table to look this info up using lHash
4746 * instead of an O(n) search */
4747 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
) ||
4748 (pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
))
4750 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
, szName
))
4752 *pDescKind
= DESCKIND_TYPECOMP
;
4753 pBindPtr
->lptcomp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4754 ITypeComp_AddRef(pBindPtr
->lptcomp
);
4755 TRACE("module or enum: %s\n", debugstr_w(szName
));
4760 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
) ||
4761 (pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
))
4763 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4766 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4767 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
4769 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
4772 else if (hr
== TYPE_E_TYPEMISMATCH
)
4776 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_COCLASS
) &&
4777 (pTypeInfo
->TypeAttr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
4779 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4781 ITypeInfo
*subtypeinfo
;
4783 DESCKIND subdesckind
;
4785 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
4786 &subtypeinfo
, &subdesckind
, &subbindptr
);
4787 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
4789 TYPEDESC tdesc_appobject
=
4792 (TYPEDESC
*)pTypeInfo
->hreftype
4796 const VARDESC vardesc_appobject
=
4799 NULL
, /* lpstrSchema */
4814 VAR_STATIC
/* varkind */
4817 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
4819 /* cleanup things filled in by Bind call so we can put our
4820 * application object data in there instead */
4821 switch (subdesckind
)
4823 case DESCKIND_FUNCDESC
:
4824 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
4826 case DESCKIND_VARDESC
:
4827 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
4832 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
4834 if (pTypeInfo
->hreftype
== -1)
4835 FIXME("no hreftype for interface %p\n", pTypeInfo
);
4837 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
4841 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
4842 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
4843 ITypeInfo_AddRef(*ppTInfo
);
4846 else if (hr
== TYPE_E_TYPEMISMATCH
)
4853 TRACE("type mismatch %s\n", debugstr_w(szName
));
4854 return TYPE_E_TYPEMISMATCH
;
4858 TRACE("name not found %s\n", debugstr_w(szName
));
4863 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4867 ITypeInfo
** ppTInfo
,
4868 ITypeComp
** ppTComp
)
4870 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4871 ITypeInfoImpl
*pTypeInfo
;
4873 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4875 for (pTypeInfo
= This
->pTypeInfo
; pTypeInfo
; pTypeInfo
= pTypeInfo
->next
)
4877 /* FIXME: should use lHash to do the search */
4878 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
, szName
))
4880 TRACE("returning %p\n", pTypeInfo
);
4881 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->lpVtbl
;
4882 ITypeInfo_AddRef(*ppTInfo
);
4883 *ppTComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4884 ITypeComp_AddRef(*ppTComp
);
4889 TRACE("not found\n");
4895 static const ITypeCompVtbl tlbtcvt
=
4898 ITypeLibComp_fnQueryInterface
,
4899 ITypeLibComp_fnAddRef
,
4900 ITypeLibComp_fnRelease
,
4902 ITypeLibComp_fnBind
,
4903 ITypeLibComp_fnBindType
4906 /*================== ITypeInfo(2) Methods ===================================*/
4907 static ITypeInfo2
* ITypeInfo_Constructor(void)
4909 ITypeInfoImpl
* pTypeInfoImpl
;
4911 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4914 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4915 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4916 pTypeInfoImpl
->ref
= 0;
4917 pTypeInfoImpl
->hreftype
= -1;
4918 pTypeInfoImpl
->TypeAttr
.memidConstructor
= MEMBERID_NIL
;
4919 pTypeInfoImpl
->TypeAttr
.memidDestructor
= MEMBERID_NIL
;
4921 TRACE("(%p)\n", pTypeInfoImpl
);
4922 return (ITypeInfo2
*) pTypeInfoImpl
;
4925 /* ITypeInfo::QueryInterface
4927 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4932 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4934 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4937 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4938 IsEqualIID(riid
,&IID_ITypeInfo
)||
4939 IsEqualIID(riid
,&IID_ITypeInfo2
))
4943 ITypeInfo_AddRef(iface
);
4944 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4947 TRACE("-- Interface: E_NOINTERFACE\n");
4948 return E_NOINTERFACE
;
4951 /* ITypeInfo::AddRef
4953 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4955 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4956 ULONG ref
= InterlockedIncrement(&This
->ref
);
4958 TRACE("(%p)->ref is %u\n",This
, ref
);
4960 if (ref
== 1 /* incremented from 0 */)
4961 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4966 static void ITypeInfo_fnDestroy(ITypeInfoImpl
*This
)
4968 TLBFuncDesc
*pFInfo
, *pFInfoNext
;
4969 TLBVarDesc
*pVInfo
, *pVInfoNext
;
4970 TLBImplType
*pImpl
, *pImplNext
;
4972 TRACE("destroying ITypeInfo(%p)\n",This
);
4974 SysFreeString(This
->Name
);
4977 SysFreeString(This
->DocString
);
4978 This
->DocString
= NULL
;
4980 SysFreeString(This
->DllName
);
4981 This
->DllName
= NULL
;
4983 for (pFInfo
= This
->funclist
; pFInfo
; pFInfo
= pFInfoNext
)
4986 for(i
= 0;i
< pFInfo
->funcdesc
.cParams
; i
++)
4988 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[i
];
4989 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4991 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
4992 TLB_Free(elemdesc
->u
.paramdesc
.pparamdescex
);
4994 SysFreeString(pFInfo
->pParamDesc
[i
].Name
);
4996 TLB_Free(pFInfo
->funcdesc
.lprgelemdescParam
);
4997 TLB_Free(pFInfo
->pParamDesc
);
4998 TLB_FreeCustData(pFInfo
->pCustData
);
4999 if (!IS_INTRESOURCE(pFInfo
->Entry
) && pFInfo
->Entry
!= (BSTR
)-1)
5000 SysFreeString(pFInfo
->Entry
);
5001 SysFreeString(pFInfo
->HelpString
);
5002 SysFreeString(pFInfo
->Name
);
5004 pFInfoNext
= pFInfo
->next
;
5007 for (pVInfo
= This
->varlist
; pVInfo
; pVInfo
= pVInfoNext
)
5009 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
5011 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5012 TLB_Free(pVInfo
->vardesc
.u
.lpvarValue
);
5014 TLB_FreeCustData(pVInfo
->pCustData
);
5015 SysFreeString(pVInfo
->Name
);
5016 pVInfoNext
= pVInfo
->next
;
5019 for (pImpl
= This
->impltypelist
; pImpl
; pImpl
= pImplNext
)
5021 TLB_FreeCustData(pImpl
->pCustData
);
5022 pImplNext
= pImpl
->next
;
5025 TLB_FreeCustData(This
->pCustData
);
5027 HeapFree(GetProcessHeap(), 0, This
);
5030 /* ITypeInfo::Release
5032 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5034 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5035 ULONG ref
= InterlockedDecrement(&This
->ref
);
5037 TRACE("(%p)->(%u)\n",This
, ref
);
5041 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5042 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
5043 if (not_attached_to_typelib
)
5044 HeapFree(GetProcessHeap(), 0, This
);
5045 /* otherwise This will be freed when typelib is freed */
5051 /* ITypeInfo::GetTypeAttr
5053 * Retrieves a TYPEATTR structure that contains the attributes of the type
5057 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5058 LPTYPEATTR
*ppTypeAttr
)
5060 const ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5063 TRACE("(%p)\n",This
);
5065 size
= sizeof(**ppTypeAttr
);
5066 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5067 size
+= TLB_SizeTypeDesc(&This
->TypeAttr
.tdescAlias
, FALSE
);
5069 *ppTypeAttr
= HeapAlloc(GetProcessHeap(), 0, size
);
5071 return E_OUTOFMEMORY
;
5073 **ppTypeAttr
= This
->TypeAttr
;
5075 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5076 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5077 &This
->TypeAttr
.tdescAlias
, *ppTypeAttr
+ 1);
5079 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5080 /* This should include all the inherited funcs */
5081 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ sizeof(void *);
5082 (*ppTypeAttr
)->cbSizeVft
= 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5083 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5088 /* ITypeInfo::GetTypeComp
5090 * Retrieves the ITypeComp interface for the type description, which enables a
5091 * client compiler to bind to the type description's members.
5094 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5095 ITypeComp
* *ppTComp
)
5097 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5099 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5101 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
5102 ITypeComp_AddRef(*ppTComp
);
5106 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5108 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5109 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5110 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5114 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5117 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5118 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5120 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5121 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5122 *buffer
+= sizeof(PARAMDESCEX
);
5123 *pparamdescex_dest
= *pparamdescex_src
;
5124 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5125 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5126 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5129 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5133 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5135 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5136 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5139 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5143 SIZE_T size
= sizeof(*src
);
5147 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5148 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5149 for (i
= 0; i
< src
->cParams
; i
++)
5151 size
+= sizeof(ELEMDESC
);
5152 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5155 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5156 if (!dest
) return E_OUTOFMEMORY
;
5159 if (dispinterface
) /* overwrite funckind */
5160 dest
->funckind
= FUNC_DISPATCH
;
5161 buffer
= (char *)(dest
+ 1);
5163 dest
->lprgscode
= (SCODE
*)buffer
;
5164 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5165 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5167 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5170 SysFreeString((BSTR
)dest
);
5174 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5175 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5176 for (i
= 0; i
< src
->cParams
; i
++)
5178 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5184 /* undo the above actions */
5185 for (i
= i
- 1; i
>= 0; i
--)
5186 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5187 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5188 SysFreeString((BSTR
)dest
);
5192 /* special treatment for dispinterfaces: this makes functions appear
5193 * to return their [retval] value when it is really returning an
5195 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5197 if (dest
->cParams
&&
5198 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5200 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5201 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5203 ERR("elemdesc should have started with VT_PTR instead of:\n");
5205 dump_ELEMDESC(elemdesc
);
5206 return E_UNEXPECTED
;
5209 /* copy last parameter to the return value. we are using a flat
5210 * buffer so there is no danger of leaking memory in
5212 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5214 /* remove the last parameter */
5218 /* otherwise this function is made to appear to have no return
5220 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5228 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5230 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5231 const TLBFuncDesc
*pFDesc
;
5234 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
5239 *ppFuncDesc
= &pFDesc
->funcdesc
;
5243 return TYPE_E_ELEMENTNOTFOUND
;
5246 /* internal function to make the inherited interfaces' methods appear
5247 * part of the interface */
5248 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5249 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5251 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5253 UINT implemented_funcs
= 0;
5258 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5260 if(This
->impltypelist
)
5262 ITypeInfo
*pSubTypeInfo
;
5265 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pSubTypeInfo
);
5269 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5272 &sub_funcs
, hrefoffset
);
5273 implemented_funcs
+= sub_funcs
;
5274 ITypeInfo_Release(pSubTypeInfo
);
5277 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5281 *funcs
= implemented_funcs
+ This
->TypeAttr
.cFuncs
;
5285 if (index
< implemented_funcs
)
5286 return E_INVALIDARG
;
5287 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5291 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5293 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5296 switch (pTypeDesc
->vt
)
5298 case VT_USERDEFINED
:
5299 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5303 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5306 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5314 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5317 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5318 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5319 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5322 /* ITypeInfo::GetFuncDesc
5324 * Retrieves the FUNCDESC structure that contains information about a
5325 * specified function.
5328 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5329 LPFUNCDESC
*ppFuncDesc
)
5331 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5332 const FUNCDESC
*internal_funcdesc
;
5334 UINT hrefoffset
= 0;
5336 TRACE("(%p) index %d\n", This
, index
);
5338 if (This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5339 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5340 &internal_funcdesc
, NULL
,
5343 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5344 &internal_funcdesc
);
5347 WARN("description for function %d not found\n", index
);
5351 hr
= TLB_AllocAndInitFuncDesc(
5354 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
5356 if ((This
->TypeAttr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
5357 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5359 TRACE("-- 0x%08x\n", hr
);
5363 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5367 SIZE_T size
= sizeof(*src
);
5370 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
5371 if (src
->varkind
== VAR_CONST
)
5372 size
+= sizeof(VARIANT
);
5373 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
5375 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
5376 if (!dest
) return E_OUTOFMEMORY
;
5379 buffer
= (char *)(dest
+ 1);
5380 if (src
->lpstrSchema
)
5383 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
5384 len
= strlenW(src
->lpstrSchema
);
5385 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
5386 buffer
+= (len
+ 1) * sizeof(WCHAR
);
5389 if (src
->varkind
== VAR_CONST
)
5393 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
5394 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
5395 buffer
+= sizeof(VARIANT
);
5396 VariantInit(dest
->u
.lpvarValue
);
5397 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
5400 SysFreeString((BSTR
)dest
);
5404 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
5407 if (src
->varkind
== VAR_CONST
)
5408 VariantClear(dest
->u
.lpvarValue
);
5409 SysFreeString((BSTR
)dest
);
5416 /* ITypeInfo::GetVarDesc
5418 * Retrieves a VARDESC structure that describes the specified variable.
5421 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
5422 LPVARDESC
*ppVarDesc
)
5424 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5426 const TLBVarDesc
*pVDesc
;
5428 TRACE("(%p) index %d\n", This
, index
);
5430 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
5434 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
5436 return E_INVALIDARG
;
5439 /* ITypeInfo_GetNames
5441 * Retrieves the variable with the specified member ID (or the name of the
5442 * property or method and its parameters) that correspond to the specified
5445 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
5446 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
5448 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5449 const TLBFuncDesc
*pFDesc
;
5450 const TLBVarDesc
*pVDesc
;
5452 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
5453 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
5456 /* function found, now return function and parameter names */
5457 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
5460 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
5462 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
5468 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
5471 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
5476 if(This
->impltypelist
&&
5477 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
5478 /* recursive search */
5481 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
5483 if(SUCCEEDED(result
))
5485 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
5486 ITypeInfo_Release(pTInfo
);
5489 WARN("Could not search inherited interface!\n");
5493 WARN("no names found\n");
5496 return TYPE_E_ELEMENTNOTFOUND
;
5503 /* ITypeInfo::GetRefTypeOfImplType
5505 * If a type description describes a COM class, it retrieves the type
5506 * description of the implemented interface types. For an interface,
5507 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5511 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
5516 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5519 const TLBImplType
*pImpl
= This
->impltypelist
;
5521 TRACE("(%p) index %d\n", This
, index
);
5522 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
5526 /* only valid on dual interfaces;
5527 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5529 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
5531 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
5537 hr
= TYPE_E_ELEMENTNOTFOUND
;
5540 else if(index
== 0 && This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5542 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5543 *pRefType
= This
->pTypeLib
->dispatch_href
;
5547 /* get element n from linked list */
5548 for(i
=0; pImpl
&& i
<index
; i
++)
5550 pImpl
= pImpl
->next
;
5554 *pRefType
= pImpl
->hRef
;
5556 hr
= TYPE_E_ELEMENTNOTFOUND
;
5562 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
5564 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
5570 /* ITypeInfo::GetImplTypeFlags
5572 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5573 * or base interface in a type description.
5575 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
5576 UINT index
, INT
*pImplTypeFlags
)
5578 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5582 TRACE("(%p) index %d\n", This
, index
);
5583 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
5584 i
++, pImpl
=pImpl
->next
)
5586 if(i
==index
&& pImpl
){
5587 *pImplTypeFlags
=pImpl
->implflags
;
5592 if(This
->TypeAttr
.typekind
==TKIND_DISPATCH
&& !index
)
5595 WARN("ImplType %d not found\n", index
);
5596 return TYPE_E_ELEMENTNOTFOUND
;
5600 * Maps between member names and member IDs, and parameter names and
5603 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
5604 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
5606 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5607 const TLBFuncDesc
*pFDesc
;
5608 const TLBVarDesc
*pVDesc
;
5612 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
5615 /* init out parameters in case of failure */
5616 for (i
= 0; i
< cNames
; i
++)
5617 pMemId
[i
] = MEMBERID_NIL
;
5619 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
5621 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
5622 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
5623 for(i
=1; i
< cNames
; i
++){
5624 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
5625 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
5627 if( j
<pFDesc
->funcdesc
.cParams
)
5630 ret
=DISP_E_UNKNOWNNAME
;
5632 TRACE("-- 0x%08x\n", ret
);
5636 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
5637 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
5638 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
5642 /* not found, see if it can be found in an inherited interface */
5643 if(This
->impltypelist
) {
5644 /* recursive search */
5646 ret
=ITypeInfo_GetRefTypeInfo(iface
,
5647 This
->impltypelist
->hRef
, &pTInfo
);
5649 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
5650 ITypeInfo_Release(pTInfo
);
5653 WARN("Could not search inherited interface!\n");
5655 WARN("no names found\n");
5656 return DISP_E_UNKNOWNNAME
;
5662 extern DWORD CDECL
call_method( void *func
, int nb_args
, const DWORD
*args
);
5663 __ASM_GLOBAL_FUNC( call_method
,
5665 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5666 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5667 "movl %esp,%ebp\n\t"
5668 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5670 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5672 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5673 "movl 12(%ebp),%edx\n\t"
5676 "subl %edx,%esp\n\t"
5677 "andl $~15,%esp\n\t"
5678 "movl 12(%ebp),%ecx\n\t"
5679 "movl 16(%ebp),%esi\n\t"
5680 "movl %esp,%edi\n\t"
5683 "1:\tcall *8(%ebp)\n\t"
5684 "leal -8(%ebp),%esp\n\t"
5686 __ASM_CFI(".cfi_same_value %edi\n\t")
5688 __ASM_CFI(".cfi_same_value %esi\n\t")
5690 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5691 __ASM_CFI(".cfi_same_value %ebp\n\t")
5694 /* ITypeInfo::Invoke
5696 * Invokes a method, or accesses a property of an object, that implements the
5697 * interface described by the type description.
5700 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
5703 if (TRACE_ON(ole
)) {
5705 TRACE("Calling %p(",func
);
5706 for (i
=0;i
<nrargs
;i
++) TRACE("%08x,",args
[i
]);
5713 res
= call_method( func
, nrargs
, args
);
5716 FIXME("unsupported calling convention %d\n",callconv
);
5720 TRACE("returns %08x\n",res
);
5724 /* The size of the argument on the stack in DWORD units (in all x86 call
5725 * convetions the arguments on the stack are DWORD-aligned)
5727 static int _dispargsize(VARTYPE vt
)
5732 return 8/sizeof(DWORD
);
5734 return sizeof(double)/sizeof(DWORD
);
5736 return (sizeof(DECIMAL
)+3)/sizeof(DWORD
);
5738 return sizeof(CY
)/sizeof(DWORD
);
5740 return sizeof(DATE
)/sizeof(DWORD
);
5742 return (sizeof(VARIANT
)+3)/sizeof(DWORD
);
5744 FIXME("VT_RECORD not implemented\n");
5750 #endif /* __i386__ */
5752 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5755 ITypeInfo
*tinfo2
= NULL
;
5756 TYPEATTR
*tattr
= NULL
;
5758 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
5761 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5763 tdesc
->u
.hreftype
, hr
);
5766 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
5769 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
5770 ITypeInfo_Release(tinfo2
);
5774 switch (tattr
->typekind
)
5781 tdesc
= &tattr
->tdescAlias
;
5782 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
5785 case TKIND_INTERFACE
:
5786 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
5792 case TKIND_DISPATCH
:
5801 FIXME("TKIND_RECORD unhandled.\n");
5806 FIXME("TKIND_UNION unhandled.\n");
5811 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
5815 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
5816 ITypeInfo_Release(tinfo2
);
5820 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5824 /* enforce only one level of pointer indirection */
5825 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
5827 tdesc
= tdesc
->u
.lptdesc
;
5829 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5830 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5831 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5832 if ((tdesc
->vt
== VT_USERDEFINED
) ||
5833 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
5835 VARTYPE vt_userdefined
= 0;
5836 const TYPEDESC
*tdesc_userdefined
= tdesc
;
5837 if (tdesc
->vt
== VT_PTR
)
5839 vt_userdefined
= VT_BYREF
;
5840 tdesc_userdefined
= tdesc
->u
.lptdesc
;
5842 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
5844 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
5845 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
5847 *vt
|= vt_userdefined
;
5859 case VT_USERDEFINED
:
5860 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
5867 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
5868 hr
= DISP_E_BADVARTYPE
;
5872 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
5887 /***********************************************************************
5888 * DispCallFunc (OLEAUT32.@)
5890 * Invokes a function of the specified calling convention, passing the
5891 * specified arguments and returns the result.
5894 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5895 * oVft [I] The offset in the vtable. See notes.
5896 * cc [I] Calling convention of the function to call.
5897 * vtReturn [I] The return type of the function.
5898 * cActuals [I] Number of parameters.
5899 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5900 * prgpvarg [I] The arguments to pass.
5901 * pvargResult [O] The return value of the function. Can be NULL.
5905 * Failure: HRESULT code.
5908 * The HRESULT return value of this function is not affected by the return
5909 * value of the user supplied function, which is returned in pvargResult.
5911 * If pvInstance is NULL then a non-object function is to be called and oVft
5912 * is the address of the function to call.
5914 * The cc parameter can be one of the following values:
5927 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
5928 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
5931 int argsize
, argspos
;
5936 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5937 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
5938 pvargResult
, V_VT(pvargResult
));
5942 argsize
++; /* for This pointer */
5944 for (i
=0;i
<cActuals
;i
++)
5946 TRACE("arg %u: type %d, size %d\n",i
,prgvt
[i
],_dispargsize(prgvt
[i
]));
5947 dump_Variant(prgpvarg
[i
]);
5948 argsize
+= _dispargsize(prgvt
[i
]);
5950 args
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
5955 args
[0] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
5959 for (i
=0;i
<cActuals
;i
++)
5961 VARIANT
*arg
= prgpvarg
[i
];
5962 TRACE("Storing arg %u (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
5963 if (prgvt
[i
] == VT_VARIANT
)
5964 memcpy(&args
[argspos
], arg
, _dispargsize(prgvt
[i
]) * sizeof(DWORD
));
5966 memcpy(&args
[argspos
], &V_NONE(arg
), _dispargsize(prgvt
[i
]) * sizeof(DWORD
));
5967 argspos
+= _dispargsize(prgvt
[i
]);
5972 FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
5973 hres
= _invoke(vtable
[oVft
/sizeof(void *)], cc
, argsize
, args
);
5976 /* if we aren't invoking an object then the function pointer is stored
5978 hres
= _invoke((FARPROC
)oVft
, cc
, argsize
, args
);
5980 if (pvargResult
&& (vtReturn
!= VT_EMPTY
))
5982 TRACE("Method returned 0x%08x\n",hres
);
5983 V_VT(pvargResult
) = vtReturn
;
5984 V_UI4(pvargResult
) = hres
;
5986 HeapFree(GetProcessHeap(),0,args
);
5989 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
5990 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
5995 #define INVBUF_ELEMENT_SIZE \
5996 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5997 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5998 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5999 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6000 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6001 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6002 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6003 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6005 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6010 DISPPARAMS
*pDispParams
,
6011 VARIANT
*pVarResult
,
6012 EXCEPINFO
*pExcepInfo
,
6015 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6017 unsigned int var_index
;
6020 const TLBFuncDesc
*pFuncInfo
;
6022 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6023 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6028 ERR("NULL pDispParams not allowed\n");
6029 return E_INVALIDARG
;
6032 dump_DispParms(pDispParams
);
6034 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6036 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6037 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6038 return E_INVALIDARG
;
6041 /* we do this instead of using GetFuncDesc since it will return a fake
6042 * FUNCDESC for dispinterfaces and we want the real function description */
6043 for (pFuncInfo
= This
->funclist
; pFuncInfo
; pFuncInfo
=pFuncInfo
->next
)
6044 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6045 (wFlags
& pFuncInfo
->funcdesc
.invkind
))
6049 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6053 TRACE("invoking:\n");
6054 dump_TLBFuncDescOne(pFuncInfo
);
6057 switch (func_desc
->funckind
) {
6058 case FUNC_PUREVIRTUAL
:
6059 case FUNC_VIRTUAL
: {
6060 void *buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6062 VARIANT retval
; /* pointer for storing byref retvals in */
6063 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6064 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6065 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6066 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6067 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6068 UINT vargs_converted
=0;
6072 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6074 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6076 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6077 hres
= DISP_E_PARAMNOTFOUND
;
6082 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6084 ERR("functions with the vararg attribute do not support named arguments\n");
6085 hres
= DISP_E_NONAMEDARGS
;
6089 for (i
= 0; i
< func_desc
->cParams
; i
++)
6091 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6092 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6097 TRACE("changing args\n");
6098 for (i
= 0; i
< func_desc
->cParams
; i
++)
6100 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6101 VARIANTARG
*src_arg
;
6103 if (wParamFlags
& PARAMFLAG_FLCID
)
6106 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6108 V_I4(arg
) = This
->pTypeLib
->lcid
;
6117 for (j
= 0; j
< cNamedArgs
; j
++)
6118 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6120 src_arg
= &pDispParams
->rgvarg
[j
];
6125 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6127 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6131 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6133 /* under most conditions the caller is not allowed to
6134 * pass in a dispparam arg in the index of what would be
6135 * the retval parameter. however, there is an exception
6136 * where the extra parameter is used in an extra
6137 * IDispatch::Invoke below */
6138 if ((i
< pDispParams
->cArgs
) &&
6139 ((func_desc
->cParams
!= 1) || !pVarResult
||
6140 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
6142 hres
= DISP_E_BADPARAMCOUNT
;
6146 /* note: this check is placed so that if the caller passes
6147 * in a VARIANTARG for the retval we just ignore it, like
6149 if (i
== func_desc
->cParams
- 1)
6152 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6153 memset(arg
, 0, sizeof(*arg
));
6154 V_VT(arg
) = rgvt
[i
];
6155 memset(&retval
, 0, sizeof(retval
));
6156 V_BYREF(arg
) = &retval
;
6160 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
6161 hres
= E_UNEXPECTED
;
6167 dump_Variant(src_arg
);
6169 if (rgvt
[i
] == VT_VARIANT
)
6170 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
6171 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
6173 if (rgvt
[i
] == V_VT(src_arg
))
6174 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
6177 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6178 if (wParamFlags
& PARAMFLAG_FIN
)
6179 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
6180 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
6182 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6184 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
6187 SAFEARRAYBOUND bound
;
6191 bound
.cElements
= pDispParams
->cArgs
-i
;
6192 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
6194 ERR("SafeArrayCreate failed\n");
6197 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6200 ERR("SafeArrayAccessData failed with %x\n", hres
);
6203 for (j
= 0; j
< bound
.cElements
; j
++)
6204 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
6205 hres
= SafeArrayUnaccessData(a
);
6208 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6211 V_ARRAY(&rgvarg
[i
]) = a
;
6212 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6214 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
6216 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6217 if (wParamFlags
& PARAMFLAG_FIN
)
6218 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
6220 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
6221 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
6222 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6224 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
6226 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
6227 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6231 /* FIXME: this doesn't work for VT_BYREF arguments if
6232 * they are not the same type as in the paramdesc */
6233 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
6234 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
6235 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6240 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
6241 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
6242 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
6245 prgpvarg
[i
] = &rgvarg
[i
];
6247 else if (wParamFlags
& PARAMFLAG_FOPT
)
6250 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6251 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6253 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
6259 VARIANTARG
*missing_arg
;
6260 /* if the function wants a pointer to a variant then
6261 * set that up, otherwise just pass the VT_ERROR in
6262 * the argument by value */
6263 if (rgvt
[i
] & VT_BYREF
)
6265 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
6266 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
6267 V_VARIANTREF(arg
) = missing_arg
;
6271 V_VT(missing_arg
) = VT_ERROR
;
6272 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
6277 hres
= DISP_E_BADPARAMCOUNT
;
6281 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6283 /* VT_VOID is a special case for return types, so it is not
6284 * handled in the general function */
6285 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
6286 V_VT(&varresult
) = VT_EMPTY
;
6289 V_VT(&varresult
) = 0;
6290 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
6291 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6294 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
, func_desc
->callconv
,
6295 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
6296 prgpvarg
, &varresult
);
6298 vargs_converted
= 0;
6300 for (i
= 0; i
< func_desc
->cParams
; i
++)
6302 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6303 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6305 if (wParamFlags
& PARAMFLAG_FLCID
)
6307 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
6311 TRACE("[retval] value: ");
6312 dump_Variant(prgpvarg
[i
]);
6317 VariantInit(pVarResult
);
6318 /* deref return value */
6319 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
6322 VARIANT_ClearInd(prgpvarg
[i
]);
6324 else if (vargs_converted
< pDispParams
->cArgs
)
6326 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6327 if (wParamFlags
& PARAMFLAG_FOUT
)
6329 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
6331 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
6335 ERR("failed to convert param %d to vt %d\n", i
,
6336 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
6341 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
6342 func_desc
->cParamsOpt
< 0 &&
6343 i
== func_desc
->cParams
-1)
6345 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
6348 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
6351 ERR("SafeArrayGetUBound failed with %x\n", hres
);
6354 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6357 ERR("SafeArrayAccessData failed with %x\n", hres
);
6360 for (j
= 0; j
<= ubound
; j
++)
6361 VariantClear(&v
[j
]);
6362 hres
= SafeArrayUnaccessData(a
);
6365 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6369 VariantClear(&rgvarg
[i
]);
6372 else if (wParamFlags
& PARAMFLAG_FOPT
)
6374 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6375 VariantClear(&rgvarg
[i
]);
6378 VariantClear(&missing_arg
[i
]);
6381 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
6383 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
6384 hres
= DISP_E_EXCEPTION
;
6387 IErrorInfo
*pErrorInfo
;
6388 pExcepInfo
->scode
= V_ERROR(&varresult
);
6389 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
6391 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
6392 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
6393 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
6394 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
6396 IErrorInfo_Release(pErrorInfo
);
6400 if (V_VT(&varresult
) != VT_ERROR
)
6402 TRACE("varresult value: ");
6403 dump_Variant(&varresult
);
6407 VariantClear(pVarResult
);
6408 *pVarResult
= varresult
;
6411 VariantClear(&varresult
);
6414 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
6415 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
6416 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
6417 (pDispParams
->cArgs
!= 0))
6419 if (V_VT(pVarResult
) == VT_DISPATCH
)
6421 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
6422 /* Note: not VariantClear; we still need the dispatch
6423 * pointer to be valid */
6424 VariantInit(pVarResult
);
6425 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
6426 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
6427 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
6428 IDispatch_Release(pDispatch
);
6432 VariantClear(pVarResult
);
6433 hres
= DISP_E_NOTACOLLECTION
;
6438 HeapFree(GetProcessHeap(), 0, buffer
);
6441 case FUNC_DISPATCH
: {
6444 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
6445 if (SUCCEEDED(hres
)) {
6446 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6447 hres
= IDispatch_Invoke(
6448 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
6449 pVarResult
,pExcepInfo
,pArgErr
6452 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
6453 IDispatch_Release(disp
);
6455 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6459 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
6464 TRACE("-- 0x%08x\n", hres
);
6467 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
6470 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
6471 if(FAILED(hres
)) return hres
;
6473 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6474 dump_VARDESC(var_desc
);
6475 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
6479 /* not found, look for it in inherited interfaces */
6480 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
6481 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
6482 if(This
->impltypelist
) {
6483 /* recursive search */
6485 hres
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pTInfo
);
6486 if(SUCCEEDED(hres
)){
6487 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
6488 ITypeInfo_Release(pTInfo
);
6491 WARN("Could not search inherited interface!\n");
6494 ERR("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
6495 return DISP_E_MEMBERNOTFOUND
;
6498 /* ITypeInfo::GetDocumentation
6500 * Retrieves the documentation string, the complete Help file name and path,
6501 * and the context ID for the Help topic for a specified type description.
6503 * (Can be tested by the Visual Basic Editor in Word for instance.)
6505 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
6506 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
6507 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
6509 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6510 const TLBFuncDesc
*pFDesc
;
6511 const TLBVarDesc
*pVDesc
;
6512 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6513 " HelpContext(%p) HelpFile(%p)\n",
6514 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6515 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
6517 *pBstrName
=SysAllocString(This
->Name
);
6519 *pBstrDocString
=SysAllocString(This
->DocString
);
6521 *pdwHelpContext
=This
->dwHelpContext
;
6523 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
6525 }else {/* for a member */
6526 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6527 if(pFDesc
->funcdesc
.memid
==memid
){
6529 *pBstrName
= SysAllocString(pFDesc
->Name
);
6531 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
6533 *pdwHelpContext
=pFDesc
->helpcontext
;
6536 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
6537 if(pVDesc
->vardesc
.memid
==memid
){
6539 *pBstrName
= SysAllocString(pVDesc
->Name
);
6541 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
6543 *pdwHelpContext
=pVDesc
->HelpContext
;
6548 if(This
->impltypelist
&&
6549 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
6550 /* recursive search */
6553 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
6555 if(SUCCEEDED(result
)) {
6556 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
6557 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6558 ITypeInfo_Release(pTInfo
);
6561 WARN("Could not search inherited interface!\n");
6564 WARN("member %d not found\n", memid
);
6565 return TYPE_E_ELEMENTNOTFOUND
;
6568 /* ITypeInfo::GetDllEntry
6570 * Retrieves a description or specification of an entry point for a function
6573 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
6574 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
6577 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6578 const TLBFuncDesc
*pFDesc
;
6580 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
6582 if (pBstrDllName
) *pBstrDllName
= NULL
;
6583 if (pBstrName
) *pBstrName
= NULL
;
6584 if (pwOrdinal
) *pwOrdinal
= 0;
6586 if (This
->TypeAttr
.typekind
!= TKIND_MODULE
)
6587 return TYPE_E_BADMODULEKIND
;
6589 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6590 if(pFDesc
->funcdesc
.memid
==memid
){
6591 dump_TypeInfo(This
);
6593 dump_TLBFuncDescOne(pFDesc
);
6596 *pBstrDllName
= SysAllocString(This
->DllName
);
6598 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
6600 *pBstrName
= SysAllocString(pFDesc
->Entry
);
6608 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
6611 return TYPE_E_ELEMENTNOTFOUND
;
6614 /* internal function to make the inherited interfaces' methods appear
6615 * part of the interface */
6616 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
6617 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
6619 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6622 TRACE("%p, 0x%x\n", iface
, *hRefType
);
6624 if (This
->impltypelist
&& (*hRefType
& DISPATCH_HREF_MASK
))
6626 ITypeInfo
*pSubTypeInfo
;
6628 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pSubTypeInfo
);
6632 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
6634 ITypeInfo_Release(pSubTypeInfo
);
6638 *hRefType
-= DISPATCH_HREF_OFFSET
;
6640 if (!(*hRefType
& DISPATCH_HREF_MASK
))
6641 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
6646 /* ITypeInfo::GetRefTypeInfo
6648 * If a type description references other type descriptions, it retrieves
6649 * the referenced type descriptions.
6651 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
6654 ITypeInfo
**ppTInfo
)
6656 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6657 HRESULT result
= E_FAIL
;
6659 if ((This
->hreftype
!= -1) && (This
->hreftype
== hRefType
))
6661 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6662 ITypeInfo_AddRef(*ppTInfo
);
6665 else if (hRefType
== -1 &&
6666 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
6667 (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
6669 /* when we meet a DUAL dispinterface, we must create the interface
6672 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
6675 /* the interface version contains the same information as the dispinterface
6676 * copy the contents of the structs.
6678 *pTypeInfoImpl
= *This
;
6679 pTypeInfoImpl
->ref
= 0;
6681 /* change the type to interface */
6682 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
6684 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
6686 /* the AddRef implicitly adds a reference to the parent typelib, which
6687 * stops the copied data from being destroyed until the new typeinfo's
6688 * refcount goes to zero, but we need to signal to the new instance to
6689 * not free its data structures when it is destroyed */
6690 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
6692 ITypeInfo_AddRef(*ppTInfo
);
6696 } else if ((hRefType
!= -1) && (hRefType
& DISPATCH_HREF_MASK
) &&
6697 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
))
6699 HREFTYPE href_dispatch
= hRefType
;
6700 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
6702 TLBRefType
*ref_type
;
6703 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
6705 if(ref_type
->reference
== hRefType
)
6708 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
6710 FIXME("Can't find pRefType for ref %x\n", hRefType
);
6713 if(hRefType
!= -1) {
6714 ITypeLib
*pTLib
= NULL
;
6716 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
6718 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
6720 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
6721 TRACE("typeinfo in imported typelib that is already loaded\n");
6722 pTLib
= (ITypeLib
*)ref_type
->pImpTLInfo
->pImpTypeLib
;
6723 ITypeLib2_AddRef(pTLib
);
6726 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6727 result
= LoadRegTypeLib( &ref_type
->pImpTLInfo
->guid
,
6728 ref_type
->pImpTLInfo
->wVersionMajor
,
6729 ref_type
->pImpTLInfo
->wVersionMinor
,
6730 ref_type
->pImpTLInfo
->lcid
,
6733 if(FAILED(result
)) {
6734 BSTR libnam
=SysAllocString(ref_type
->pImpTLInfo
->name
);
6735 result
=LoadTypeLib(libnam
, &pTLib
);
6736 SysFreeString(libnam
);
6738 if(SUCCEEDED(result
)) {
6739 ref_type
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
6740 ITypeLib2_AddRef(pTLib
);
6744 if(SUCCEEDED(result
)) {
6745 if(ref_type
->index
== TLB_REF_USE_GUID
)
6746 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
6750 result
= ITypeLib2_GetTypeInfo(pTLib
, ref_type
->index
,
6754 ITypeLib2_Release(pTLib
);
6759 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
6760 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
6764 /* ITypeInfo::AddressOfMember
6766 * Retrieves the addresses of static functions or variables, such as those
6769 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
6770 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
6772 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6778 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
6780 hr
= ITypeInfo_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
6784 module
= LoadLibraryW(dll
);
6787 ERR("couldn't load %s\n", debugstr_w(dll
));
6789 SysFreeString(entry
);
6790 return STG_E_FILENOTFOUND
;
6792 /* FIXME: store library somewhere where we can free it */
6797 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
6798 entryA
= HeapAlloc(GetProcessHeap(), 0, len
);
6799 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
6801 *ppv
= GetProcAddress(module
, entryA
);
6803 ERR("function not found %s\n", debugstr_a(entryA
));
6805 HeapFree(GetProcessHeap(), 0, entryA
);
6809 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
6811 ERR("function not found %d\n", ordinal
);
6815 SysFreeString(entry
);
6818 return TYPE_E_DLLFUNCTIONNOTFOUND
;
6823 /* ITypeInfo::CreateInstance
6825 * Creates a new instance of a type that describes a component object class
6828 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
6829 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
6831 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6835 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
6841 WARN("Not able to aggregate\n");
6842 return CLASS_E_NOAGGREGATION
;
6845 hr
= ITypeInfo_GetTypeAttr(iface
, &pTA
);
6846 if(FAILED(hr
)) return hr
;
6848 if(pTA
->typekind
!= TKIND_COCLASS
)
6850 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
6856 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
6859 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
6860 TRACE("GetActiveObject rets %08x\n", hr
);
6863 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
6864 IUnknown_Release(pUnk
);
6869 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
6870 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
6874 ITypeInfo_ReleaseTypeAttr(iface
, pTA
);
6878 /* ITypeInfo::GetMops
6880 * Retrieves marshalling information.
6882 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
6885 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6886 FIXME("(%p %d) stub!\n", This
, memid
);
6891 /* ITypeInfo::GetContainingTypeLib
6893 * Retrieves the containing type library and the index of the type description
6894 * within that type library.
6896 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
6897 ITypeLib
* *ppTLib
, UINT
*pIndex
)
6899 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6901 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6903 *pIndex
=This
->index
;
6904 TRACE("returning pIndex=%d\n", *pIndex
);
6908 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
6909 ITypeLib2_AddRef(*ppTLib
);
6910 TRACE("returning ppTLib=%p\n", *ppTLib
);
6916 /* ITypeInfo::ReleaseTypeAttr
6918 * Releases a TYPEATTR previously returned by GetTypeAttr.
6921 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
6922 TYPEATTR
* pTypeAttr
)
6924 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6925 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
6926 HeapFree(GetProcessHeap(), 0, pTypeAttr
);
6929 /* ITypeInfo::ReleaseFuncDesc
6931 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6933 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
6935 FUNCDESC
*pFuncDesc
)
6937 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6940 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
6942 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6943 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
6944 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
6946 SysFreeString((BSTR
)pFuncDesc
);
6949 /* ITypeInfo::ReleaseVarDesc
6951 * Releases a VARDESC previously returned by GetVarDesc.
6953 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
6956 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6957 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
6959 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
6960 if (pVarDesc
->varkind
== VAR_CONST
)
6961 VariantClear(pVarDesc
->u
.lpvarValue
);
6962 SysFreeString((BSTR
)pVarDesc
);
6965 /* ITypeInfo2::GetTypeKind
6967 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6970 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
6971 TYPEKIND
*pTypeKind
)
6973 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6974 *pTypeKind
=This
->TypeAttr
.typekind
;
6975 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
6979 /* ITypeInfo2::GetTypeFlags
6981 * Returns the type flags without any allocations. This returns a DWORD type
6982 * flag, which expands the type flags without growing the TYPEATTR (type
6986 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
6988 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6989 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
6990 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
6994 /* ITypeInfo2::GetFuncIndexOfMemId
6995 * Binds to a specific member based on a known DISPID, where the member name
6996 * is not known (for example, when binding to a default member).
6999 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7000 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7002 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7003 const TLBFuncDesc
*pFuncInfo
;
7007 for(i
= 0, pFuncInfo
= This
->funclist
; pFuncInfo
; i
++, pFuncInfo
=pFuncInfo
->next
)
7008 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7014 result
= TYPE_E_ELEMENTNOTFOUND
;
7016 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7017 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7021 /* TypeInfo2::GetVarIndexOfMemId
7023 * Binds to a specific member based on a known DISPID, where the member name
7024 * is not known (for example, when binding to a default member).
7027 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7028 MEMBERID memid
, UINT
*pVarIndex
)
7030 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7031 TLBVarDesc
*pVarInfo
;
7034 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
7035 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
7041 result
= TYPE_E_ELEMENTNOTFOUND
;
7043 TRACE("(%p) memid 0x%08x -> %s\n", This
,
7044 memid
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7048 /* ITypeInfo2::GetCustData
7050 * Gets the custom data
7052 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7057 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7058 TLBCustData
*pCData
;
7060 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
7061 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7063 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7065 VariantInit( pVarVal
);
7067 VariantCopy( pVarVal
, &pCData
->data
);
7069 VariantClear( pVarVal
);
7073 /* ITypeInfo2::GetFuncCustData
7075 * Gets the custom data
7077 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
7083 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7084 TLBCustData
*pCData
=NULL
;
7085 TLBFuncDesc
* pFDesc
;
7087 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
7088 pFDesc
=pFDesc
->next
);
7091 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
7092 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7094 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7097 VariantInit( pVarVal
);
7098 VariantCopy( pVarVal
, &pCData
->data
);
7101 return E_INVALIDARG
; /* FIXME: correct? */
7104 /* ITypeInfo2::GetParamCustData
7106 * Gets the custom data
7108 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
7115 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7116 TLBCustData
*pCData
=NULL
;
7117 TLBFuncDesc
* pFDesc
;
7120 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
7122 if(pFDesc
&& indexParam
<pFDesc
->funcdesc
.cParams
)
7123 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
7124 pCData
= pCData
->next
)
7125 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7127 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7131 VariantInit( pVarVal
);
7132 VariantCopy( pVarVal
, &pCData
->data
);
7135 return E_INVALIDARG
; /* FIXME: correct? */
7138 /* ITypeInfo2::GetVarCustData
7140 * Gets the custom data
7142 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
7148 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7149 TLBCustData
*pCData
=NULL
;
7150 TLBVarDesc
* pVDesc
;
7153 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
7157 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
7159 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7163 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7167 VariantInit( pVarVal
);
7168 VariantCopy( pVarVal
, &pCData
->data
);
7171 return E_INVALIDARG
; /* FIXME: correct? */
7174 /* ITypeInfo2::GetImplCustData
7176 * Gets the custom data
7178 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
7184 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7185 TLBCustData
*pCData
=NULL
;
7186 TLBImplType
* pRDesc
;
7189 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
7193 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
7195 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7199 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7203 VariantInit( pVarVal
);
7204 VariantCopy( pVarVal
, &pCData
->data
);
7207 return E_INVALIDARG
; /* FIXME: correct? */
7210 /* ITypeInfo2::GetDocumentation2
7212 * Retrieves the documentation string, the complete Help file name and path,
7213 * the localization context to use, and the context ID for the library Help
7214 * topic in the Help file.
7217 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
7221 BSTR
*pbstrHelpString
,
7222 DWORD
*pdwHelpStringContext
,
7223 BSTR
*pbstrHelpStringDll
)
7225 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7226 const TLBFuncDesc
*pFDesc
;
7227 const TLBVarDesc
*pVDesc
;
7228 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7229 "HelpStringContext(%p) HelpStringDll(%p)\n",
7230 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
7231 pbstrHelpStringDll
);
7232 /* the help string should be obtained from the helpstringdll,
7233 * using the _DLLGetDocumentation function, based on the supplied
7234 * lcid. Nice to do sometime...
7236 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7238 *pbstrHelpString
=SysAllocString(This
->Name
);
7239 if(pdwHelpStringContext
)
7240 *pdwHelpStringContext
=This
->dwHelpStringContext
;
7241 if(pbstrHelpStringDll
)
7242 *pbstrHelpStringDll
=
7243 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7245 }else {/* for a member */
7246 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
7247 if(pFDesc
->funcdesc
.memid
==memid
){
7249 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
7250 if(pdwHelpStringContext
)
7251 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
7252 if(pbstrHelpStringDll
)
7253 *pbstrHelpStringDll
=
7254 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7257 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
7258 if(pVDesc
->vardesc
.memid
==memid
){
7260 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
7261 if(pdwHelpStringContext
)
7262 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
7263 if(pbstrHelpStringDll
)
7264 *pbstrHelpStringDll
=
7265 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7269 return TYPE_E_ELEMENTNOTFOUND
;
7272 /* ITypeInfo2::GetAllCustData
7274 * Gets all custom data items for the Type info.
7277 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
7279 CUSTDATA
*pCustData
)
7281 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7282 TLBCustData
*pCData
;
7285 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
7287 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
7288 if(pCustData
->prgCustData
){
7289 pCustData
->cCustData
=This
->ctCustData
;
7290 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
7291 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7292 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
7295 ERR(" OUT OF MEMORY!\n");
7296 return E_OUTOFMEMORY
;
7301 /* ITypeInfo2::GetAllFuncCustData
7303 * Gets all custom data items for the specified Function
7306 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
7309 CUSTDATA
*pCustData
)
7311 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7312 TLBCustData
*pCData
;
7313 TLBFuncDesc
* pFDesc
;
7315 TRACE("(%p) index %d\n", This
, index
);
7316 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
7317 pFDesc
=pFDesc
->next
)
7320 pCustData
->prgCustData
=
7321 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
7322 if(pCustData
->prgCustData
){
7323 pCustData
->cCustData
=pFDesc
->ctCustData
;
7324 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
7325 pCData
= pCData
->next
){
7326 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7327 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7331 ERR(" OUT OF MEMORY!\n");
7332 return E_OUTOFMEMORY
;
7336 return TYPE_E_ELEMENTNOTFOUND
;
7339 /* ITypeInfo2::GetAllParamCustData
7341 * Gets all custom data items for the Functions
7344 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
7345 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
7347 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7348 TLBCustData
*pCData
=NULL
;
7349 TLBFuncDesc
* pFDesc
;
7351 TRACE("(%p) index %d\n", This
, indexFunc
);
7352 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
7353 pFDesc
=pFDesc
->next
)
7355 if(pFDesc
&& indexParam
<pFDesc
->funcdesc
.cParams
){
7356 pCustData
->prgCustData
=
7357 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
7358 sizeof(CUSTDATAITEM
));
7359 if(pCustData
->prgCustData
){
7360 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
7361 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
7362 pCData
; i
++, pCData
= pCData
->next
){
7363 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7364 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7368 ERR(" OUT OF MEMORY!\n");
7369 return E_OUTOFMEMORY
;
7373 return TYPE_E_ELEMENTNOTFOUND
;
7376 /* ITypeInfo2::GetAllVarCustData
7378 * Gets all custom data items for the specified Variable
7381 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
7382 UINT index
, CUSTDATA
*pCustData
)
7384 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7385 TLBCustData
*pCData
;
7386 TLBVarDesc
* pVDesc
;
7388 TRACE("(%p) index %d\n", This
, index
);
7389 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
7390 pVDesc
=pVDesc
->next
)
7393 pCustData
->prgCustData
=
7394 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
7395 if(pCustData
->prgCustData
){
7396 pCustData
->cCustData
=pVDesc
->ctCustData
;
7397 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
7398 pCData
= pCData
->next
){
7399 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7400 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7404 ERR(" OUT OF MEMORY!\n");
7405 return E_OUTOFMEMORY
;
7409 return TYPE_E_ELEMENTNOTFOUND
;
7412 /* ITypeInfo2::GetAllImplCustData
7414 * Gets all custom data items for the specified implementation type
7417 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
7420 CUSTDATA
*pCustData
)
7422 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7423 TLBCustData
*pCData
;
7424 TLBImplType
* pRDesc
;
7426 TRACE("(%p) index %d\n", This
, index
);
7427 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
7428 pRDesc
=pRDesc
->next
)
7431 pCustData
->prgCustData
=
7432 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
7433 if(pCustData
->prgCustData
){
7434 pCustData
->cCustData
=pRDesc
->ctCustData
;
7435 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
7436 pCData
= pCData
->next
){
7437 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7438 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7442 ERR(" OUT OF MEMORY!\n");
7443 return E_OUTOFMEMORY
;
7447 return TYPE_E_ELEMENTNOTFOUND
;
7450 static const ITypeInfo2Vtbl tinfvt
=
7453 ITypeInfo_fnQueryInterface
,
7455 ITypeInfo_fnRelease
,
7457 ITypeInfo_fnGetTypeAttr
,
7458 ITypeInfo_fnGetTypeComp
,
7459 ITypeInfo_fnGetFuncDesc
,
7460 ITypeInfo_fnGetVarDesc
,
7461 ITypeInfo_fnGetNames
,
7462 ITypeInfo_fnGetRefTypeOfImplType
,
7463 ITypeInfo_fnGetImplTypeFlags
,
7464 ITypeInfo_fnGetIDsOfNames
,
7466 ITypeInfo_fnGetDocumentation
,
7467 ITypeInfo_fnGetDllEntry
,
7468 ITypeInfo_fnGetRefTypeInfo
,
7469 ITypeInfo_fnAddressOfMember
,
7470 ITypeInfo_fnCreateInstance
,
7471 ITypeInfo_fnGetMops
,
7472 ITypeInfo_fnGetContainingTypeLib
,
7473 ITypeInfo_fnReleaseTypeAttr
,
7474 ITypeInfo_fnReleaseFuncDesc
,
7475 ITypeInfo_fnReleaseVarDesc
,
7477 ITypeInfo2_fnGetTypeKind
,
7478 ITypeInfo2_fnGetTypeFlags
,
7479 ITypeInfo2_fnGetFuncIndexOfMemId
,
7480 ITypeInfo2_fnGetVarIndexOfMemId
,
7481 ITypeInfo2_fnGetCustData
,
7482 ITypeInfo2_fnGetFuncCustData
,
7483 ITypeInfo2_fnGetParamCustData
,
7484 ITypeInfo2_fnGetVarCustData
,
7485 ITypeInfo2_fnGetImplTypeCustData
,
7486 ITypeInfo2_fnGetDocumentation2
,
7487 ITypeInfo2_fnGetAllCustData
,
7488 ITypeInfo2_fnGetAllFuncCustData
,
7489 ITypeInfo2_fnGetAllParamCustData
,
7490 ITypeInfo2_fnGetAllVarCustData
,
7491 ITypeInfo2_fnGetAllImplTypeCustData
,
7494 /******************************************************************************
7495 * CreateDispTypeInfo [OLEAUT32.31]
7497 * Build type information for an object so it can be called through an
7498 * IDispatch interface.
7501 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7502 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7505 * This call allows an objects methods to be accessed through IDispatch, by
7506 * building an ITypeInfo object that IDispatch can use to call through.
7508 HRESULT WINAPI
CreateDispTypeInfo(
7509 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
7510 LCID lcid
, /* [I] Locale Id */
7511 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
7513 ITypeInfoImpl
*pTIClass
, *pTIIface
;
7514 ITypeLibImpl
*pTypeLibImpl
;
7515 unsigned int param
, func
;
7516 TLBFuncDesc
**ppFuncDesc
;
7520 pTypeLibImpl
= TypeLibImpl_Constructor();
7521 if (!pTypeLibImpl
) return E_FAIL
;
7523 pTIIface
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
7524 pTIIface
->pTypeLib
= pTypeLibImpl
;
7525 pTIIface
->index
= 0;
7526 pTIIface
->Name
= NULL
;
7527 pTIIface
->dwHelpContext
= -1;
7528 memset(&pTIIface
->TypeAttr
.guid
, 0, sizeof(GUID
));
7529 pTIIface
->TypeAttr
.lcid
= lcid
;
7530 pTIIface
->TypeAttr
.typekind
= TKIND_INTERFACE
;
7531 pTIIface
->TypeAttr
.wMajorVerNum
= 0;
7532 pTIIface
->TypeAttr
.wMinorVerNum
= 0;
7533 pTIIface
->TypeAttr
.cbAlignment
= 2;
7534 pTIIface
->TypeAttr
.cbSizeInstance
= -1;
7535 pTIIface
->TypeAttr
.cbSizeVft
= -1;
7536 pTIIface
->TypeAttr
.cFuncs
= 0;
7537 pTIIface
->TypeAttr
.cImplTypes
= 0;
7538 pTIIface
->TypeAttr
.cVars
= 0;
7539 pTIIface
->TypeAttr
.wTypeFlags
= 0;
7541 ppFuncDesc
= &pTIIface
->funclist
;
7542 for(func
= 0; func
< pidata
->cMembers
; func
++) {
7543 METHODDATA
*md
= pidata
->pmethdata
+ func
;
7544 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
7545 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
7546 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
7547 (*ppFuncDesc
)->funcdesc
.lprgscode
= NULL
;
7548 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_VIRTUAL
;
7549 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
7550 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
7551 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
7552 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
7553 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
7554 (*ppFuncDesc
)->funcdesc
.cScodes
= 0;
7555 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0;
7556 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
7557 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
7558 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
7559 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
7560 md
->cArgs
* sizeof(ELEMDESC
));
7561 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
7562 md
->cArgs
* sizeof(TLBParDesc
));
7563 for(param
= 0; param
< md
->cArgs
; param
++) {
7564 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
7565 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
7567 (*ppFuncDesc
)->helpcontext
= 0;
7568 (*ppFuncDesc
)->HelpStringContext
= 0;
7569 (*ppFuncDesc
)->HelpString
= NULL
;
7570 (*ppFuncDesc
)->Entry
= NULL
;
7571 (*ppFuncDesc
)->ctCustData
= 0;
7572 (*ppFuncDesc
)->pCustData
= NULL
;
7573 (*ppFuncDesc
)->next
= NULL
;
7574 pTIIface
->TypeAttr
.cFuncs
++;
7575 ppFuncDesc
= &(*ppFuncDesc
)->next
;
7578 dump_TypeInfo(pTIIface
);
7580 pTypeLibImpl
->pTypeInfo
= pTIIface
;
7581 pTypeLibImpl
->TypeInfoCount
++;
7583 pTIClass
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
7584 pTIClass
->pTypeLib
= pTypeLibImpl
;
7585 pTIClass
->index
= 1;
7586 pTIClass
->Name
= NULL
;
7587 pTIClass
->dwHelpContext
= -1;
7588 memset(&pTIClass
->TypeAttr
.guid
, 0, sizeof(GUID
));
7589 pTIClass
->TypeAttr
.lcid
= lcid
;
7590 pTIClass
->TypeAttr
.typekind
= TKIND_COCLASS
;
7591 pTIClass
->TypeAttr
.wMajorVerNum
= 0;
7592 pTIClass
->TypeAttr
.wMinorVerNum
= 0;
7593 pTIClass
->TypeAttr
.cbAlignment
= 2;
7594 pTIClass
->TypeAttr
.cbSizeInstance
= -1;
7595 pTIClass
->TypeAttr
.cbSizeVft
= -1;
7596 pTIClass
->TypeAttr
.cFuncs
= 0;
7597 pTIClass
->TypeAttr
.cImplTypes
= 1;
7598 pTIClass
->TypeAttr
.cVars
= 0;
7599 pTIClass
->TypeAttr
.wTypeFlags
= 0;
7601 pTIClass
->impltypelist
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pTIClass
->impltypelist
));
7602 pTIClass
->impltypelist
->hRef
= 0;
7604 ref
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref
));
7607 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
7608 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
7610 dump_TypeInfo(pTIClass
);
7612 pTIIface
->next
= pTIClass
;
7613 pTypeLibImpl
->TypeInfoCount
++;
7615 *pptinfo
= (ITypeInfo
*)pTIClass
;
7617 ITypeInfo_AddRef(*pptinfo
);
7618 ITypeLib_Release((ITypeLib
*)&pTypeLibImpl
->lpVtbl
);
7624 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
7626 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7628 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
7631 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
7633 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7635 return ITypeInfo_AddRef((ITypeInfo
*)This
);
7638 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
7640 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7642 return ITypeInfo_Release((ITypeInfo
*)This
);
7645 static HRESULT WINAPI
ITypeComp_fnBind(
7650 ITypeInfo
** ppTInfo
,
7651 DESCKIND
* pDescKind
,
7654 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7655 const TLBFuncDesc
*pFDesc
;
7656 const TLBVarDesc
*pVDesc
;
7657 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
7659 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7661 *pDescKind
= DESCKIND_NONE
;
7662 pBindPtr
->lpfuncdesc
= NULL
;
7665 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
7666 if (!strcmpiW(pFDesc
->Name
, szName
)) {
7667 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
7670 /* name found, but wrong flags */
7671 hr
= TYPE_E_TYPEMISMATCH
;
7676 HRESULT hr
= TLB_AllocAndInitFuncDesc(
7678 &pBindPtr
->lpfuncdesc
,
7679 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
7682 *pDescKind
= DESCKIND_FUNCDESC
;
7683 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7684 ITypeInfo_AddRef(*ppTInfo
);
7687 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
7688 if (!strcmpiW(pVDesc
->Name
, szName
)) {
7689 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
7692 *pDescKind
= DESCKIND_VARDESC
;
7693 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7694 ITypeInfo_AddRef(*ppTInfo
);
7699 /* FIXME: search each inherited interface, not just the first */
7700 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypelist
) {
7701 /* recursive search */
7705 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
7708 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
7709 ITypeInfo_Release(pTInfo
);
7713 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7714 ITypeComp_Release(pTComp
);
7717 WARN("Could not search inherited interface!\n");
7719 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
7723 static HRESULT WINAPI
ITypeComp_fnBindType(
7727 ITypeInfo
** ppTInfo
,
7728 ITypeComp
** ppTComp
)
7730 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
7732 /* strange behaviour (does nothing) but like the
7735 if (!ppTInfo
|| !ppTComp
)
7744 static const ITypeCompVtbl tcompvt
=
7747 ITypeComp_fnQueryInterface
,
7749 ITypeComp_fnRelease
,
7752 ITypeComp_fnBindType