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
68 #include "wine/unicode.h"
71 #include "wine/debug.h"
73 #include "wine/list.h"
75 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
76 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
78 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
79 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
81 /****************************************************************************
84 * Takes p_iVal (which is in little endian) and returns it
85 * in the host machine's byte order.
87 #ifdef WORDS_BIGENDIAN
88 static WORD
FromLEWord(WORD p_iVal
)
90 return (((p_iVal
& 0x00FF) << 8) |
91 ((p_iVal
& 0xFF00) >> 8));
95 static DWORD
FromLEDWord(DWORD p_iVal
)
97 return (((p_iVal
& 0x000000FF) << 24) |
98 ((p_iVal
& 0x0000FF00) << 8) |
99 ((p_iVal
& 0x00FF0000) >> 8) |
100 ((p_iVal
& 0xFF000000) >> 24));
103 #define FromLEWord(X) (X)
104 #define FromLEDWord(X) (X)
107 #define DISPATCH_HREF_OFFSET 0x01000000
108 #define DISPATCH_HREF_MASK 0xff000000
110 /****************************************************************************
113 * Fix byte order in any structure if necessary
115 #ifdef WORDS_BIGENDIAN
116 static void FromLEWords(void *p_Val
, int p_iSize
)
120 p_iSize
/= sizeof(WORD
);
123 *Val
= FromLEWord(*Val
);
130 static void FromLEDWords(void *p_Val
, int p_iSize
)
134 p_iSize
/= sizeof(DWORD
);
137 *Val
= FromLEDWord(*Val
);
143 #define FromLEWords(X,Y) /*nothing*/
144 #define FromLEDWords(X,Y) /*nothing*/
148 * Find a typelib key which matches a requested maj.min version.
150 static BOOL
find_typelib_key( REFGUID guid
, WORD wMaj
, WORD
*wMin
)
152 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
159 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
160 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
162 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
165 len
= sizeof(key_name
);
167 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
171 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
173 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
180 break; /* exact match */
182 if (v_min
> best_min
) best_min
= v_min
;
185 len
= sizeof(key_name
);
196 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
197 /* buffer must be at least 60 characters long */
198 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
200 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
201 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
203 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
204 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
205 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
209 /* get the path of an interface key, in the form "Interface\\<guid>" */
210 /* buffer must be at least 50 characters long */
211 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
213 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
215 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
216 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
220 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
221 /* buffer must be at least 16 characters long */
222 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
224 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
225 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
226 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
228 sprintfW( buffer
, LcidFormatW
, lcid
);
231 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
232 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
234 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
240 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
243 /****************************************************************************
244 * QueryPathOfRegTypeLib [OLEAUT32.164]
246 * Gets the path to a registered type library.
249 * guid [I] referenced guid
250 * wMaj [I] major version
251 * wMin [I] minor version
253 * path [O] path of typelib
257 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
258 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
261 HRESULT WINAPI
QueryPathOfRegTypeLib(
268 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
272 WCHAR Path
[MAX_PATH
];
275 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
277 if (!find_typelib_key( guid
, wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
278 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
280 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
281 if (res
== ERROR_FILE_NOT_FOUND
)
283 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
284 return TYPE_E_LIBNOTREGISTERED
;
286 else if (res
!= ERROR_SUCCESS
)
288 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
289 return TYPE_E_REGISTRYACCESS
;
294 LONG dwPathLen
= sizeof(Path
);
296 get_lcid_subkey( myLCID
, SYS_WIN32
, buffer
);
298 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
302 else if (myLCID
== lcid
)
304 /* try with sub-langid */
305 myLCID
= SUBLANGID(lcid
);
307 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
309 /* try with system langid */
319 *path
= SysAllocString( Path
);
324 TRACE_(typelib
)("-- 0x%08x\n", hr
);
328 /******************************************************************************
329 * CreateTypeLib [OLEAUT32.160] creates a typelib
335 HRESULT WINAPI
CreateTypeLib(
336 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
338 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
342 /******************************************************************************
343 * LoadTypeLib [OLEAUT32.161]
345 * Loads a type library
348 * szFile [I] Name of file to load from.
349 * pptLib [O] Pointer that receives ITypeLib object on success.
356 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
358 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
360 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
361 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
364 /******************************************************************************
365 * LoadTypeLibEx [OLEAUT32.183]
367 * Loads and optionally registers a type library
373 HRESULT WINAPI
LoadTypeLibEx(
374 LPCOLESTR szFile
, /* [in] Name of file to load from */
375 REGKIND regkind
, /* [in] Specify kind of registration */
376 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
378 WCHAR szPath
[MAX_PATH
+1];
381 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
385 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
390 case REGKIND_DEFAULT
:
391 /* don't register typelibs supplied with full path. Experimentation confirms the following */
392 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
393 (szFile
[0] && (szFile
[1] == ':'))) break;
394 /* else fall-through */
396 case REGKIND_REGISTER
:
397 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szPath
, NULL
)))
399 IUnknown_Release(*pptLib
);
407 TRACE(" returns %08x\n",res
);
411 /******************************************************************************
412 * LoadRegTypeLib [OLEAUT32.162]
414 * Loads a registered type library.
417 * rguid [I] GUID of the registered type library.
418 * wVerMajor [I] major version.
419 * wVerMinor [I] minor version.
420 * lcid [I] locale ID.
421 * ppTLib [O] pointer that receives an ITypeLib object on success.
425 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
428 HRESULT WINAPI
LoadRegTypeLib(
440 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
444 res
= LoadTypeLib(bstr
, ppTLib
);
448 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
454 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
455 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
456 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
457 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
458 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
459 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
461 /******************************************************************************
462 * RegisterTypeLib [OLEAUT32.163]
463 * Adds information about a type library to the System Registry
465 * Docs: ITypeLib FAR * ptlib
466 * Docs: OLECHAR FAR* szFullPath
467 * Docs: OLECHAR FAR* szHelpDir
473 HRESULT WINAPI
RegisterTypeLib(
474 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
475 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
476 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
479 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
480 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
481 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
491 if (ptlib
== NULL
|| szFullPath
== NULL
)
494 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
497 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
500 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
501 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
505 /* Set the human-readable name of the typelib */
506 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
508 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
509 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
517 /* Make up the name of the typelib path subkey */
518 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
520 /* Create the typelib path subkey */
521 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
522 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
524 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
525 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
533 /* Create the flags subkey */
534 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
535 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
537 /* FIXME: is %u correct? */
538 static const WCHAR formatW
[] = {'%','u',0};
540 sprintfW(buf
, formatW
, attr
->wLibFlags
);
541 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
542 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
550 /* create the helpdir subkey */
551 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
552 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
554 BOOL freeHelpDir
= FALSE
;
557 /* if we created a new key, and helpDir was null, set the helpdir
558 to the directory which contains the typelib. However,
559 if we just opened an existing key, we leave the helpdir alone */
560 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
561 szHelpDir
= SysAllocString(szFullPath
);
562 pIndexStr
= strrchrW(szHelpDir
, '\\');
569 /* if we have an szHelpDir, set it! */
570 if (szHelpDir
!= NULL
) {
571 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
572 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
578 if (freeHelpDir
) SysFreeString(szHelpDir
);
590 /* register OLE Automation-compatible interfaces for this typelib */
591 types
= ITypeLib_GetTypeInfoCount(ptlib
);
592 for (tidx
=0; tidx
<types
; tidx
++) {
593 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
594 LPOLESTR name
= NULL
;
595 ITypeInfo
*tinfo
= NULL
;
597 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
600 case TKIND_INTERFACE
:
601 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
602 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
606 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
607 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
611 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
616 TYPEATTR
*tattr
= NULL
;
617 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
620 TRACE_(typelib
)("guid=%s, flags=%04x (",
621 debugstr_guid(&tattr
->guid
),
624 if (TRACE_ON(typelib
)) {
625 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
645 if (tattr
->wTypeFlags
& (TYPEFLAG_FOLEAUTOMATION
|TYPEFLAG_FDUAL
|TYPEFLAG_FDISPATCHABLE
))
647 /* register interface<->typelib coupling */
648 get_interface_key( &tattr
->guid
, keyName
);
649 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
650 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
653 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
654 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
656 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
657 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
658 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
659 (const BYTE
*)PSOA
, sizeof PSOA
);
663 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
664 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
665 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
666 (const BYTE
*)PSOA
, sizeof PSOA
);
670 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
671 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
674 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
675 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
677 StringFromGUID2(&attr
->guid
, buffer
, 40);
678 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
679 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
680 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
681 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
682 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
690 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
693 ITypeInfo_Release(tinfo
);
700 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
706 /******************************************************************************
707 * UnRegisterTypeLib [OLEAUT32.186]
708 * Removes information about a type library from the System Registry
715 HRESULT WINAPI
UnRegisterTypeLib(
716 REFGUID libid
, /* [in] Guid of the library */
717 WORD wVerMajor
, /* [in] major version */
718 WORD wVerMinor
, /* [in] minor version */
719 LCID lcid
, /* [in] locale id */
722 BSTR tlibPath
= NULL
;
725 WCHAR subKeyName
[50];
728 BOOL deleteOtherStuff
;
731 TYPEATTR
* typeAttr
= NULL
;
733 ITypeInfo
* typeInfo
= NULL
;
734 ITypeLib
* typeLib
= NULL
;
737 TRACE("(IID: %s)\n",debugstr_guid(libid
));
739 /* Create the path to the key */
740 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
742 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
)
744 TRACE("Unsupported syskind %i\n", syskind
);
745 result
= E_INVALIDARG
;
749 /* get the path to the typelib on disk */
750 if (QueryPathOfRegTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, &tlibPath
) != S_OK
) {
751 result
= E_INVALIDARG
;
755 /* Try and open the key to the type library. */
756 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
757 result
= E_INVALIDARG
;
761 /* Try and load the type library */
762 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
)) {
763 result
= TYPE_E_INVALIDSTATE
;
767 /* remove any types registered with this typelib */
768 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
769 for (i
=0; i
<numTypes
; i
++) {
770 /* get the kind of type */
771 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
775 /* skip non-interfaces, and get type info for the type */
776 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
779 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
782 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
786 /* the path to the type */
787 get_interface_key( &typeAttr
->guid
, subKeyName
);
789 /* Delete its bits */
790 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != ERROR_SUCCESS
) {
793 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
794 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
795 RegDeleteKeyW(subKey
, TypeLibW
);
798 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
801 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
803 if (typeInfo
) ITypeInfo_Release(typeInfo
);
807 /* Now, delete the type library path subkey */
808 get_lcid_subkey( lcid
, syskind
, subKeyName
);
809 RegDeleteKeyW(key
, subKeyName
);
810 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
811 RegDeleteKeyW(key
, subKeyName
);
813 /* check if there is anything besides the FLAGS/HELPDIR keys.
814 If there is, we don't delete them */
815 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
816 deleteOtherStuff
= TRUE
;
818 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
819 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
821 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
822 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
823 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
824 deleteOtherStuff
= FALSE
;
828 /* only delete the other parts of the key if we're absolutely sure */
829 if (deleteOtherStuff
) {
830 RegDeleteKeyW(key
, FLAGSW
);
831 RegDeleteKeyW(key
, HELPDIRW
);
835 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
836 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
837 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
841 if (tlibPath
) SysFreeString(tlibPath
);
842 if (typeLib
) ITypeLib_Release(typeLib
);
843 if (subKey
) RegCloseKey(subKey
);
844 if (key
) RegCloseKey(key
);
848 /*======================= ITypeLib implementation =======================*/
850 typedef struct tagTLBCustData
854 struct tagTLBCustData
* next
;
857 /* data structure for import typelibs */
858 typedef struct tagTLBImpLib
860 int offset
; /* offset in the file (MSFT)
861 offset in nametable (SLTG)
862 just used to identify library while reading
864 GUID guid
; /* libid */
865 BSTR name
; /* name */
867 LCID lcid
; /* lcid of imported typelib */
869 WORD wVersionMajor
; /* major version number */
870 WORD wVersionMinor
; /* minor version number */
872 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
873 NULL if not yet loaded */
874 struct tagTLBImpLib
* next
;
877 /* internal ITypeLib data */
878 typedef struct tagITypeLibImpl
880 const ITypeLib2Vtbl
*lpVtbl
;
881 const ITypeCompVtbl
*lpVtblTypeComp
;
883 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
885 /* strings can be stored in tlb as multibyte strings BUT they are *always*
886 * exported to the application as a UNICODE string.
892 unsigned long dwHelpContext
;
893 int TypeInfoCount
; /* nr of typeinfo's in librarry */
894 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
895 int ctCustData
; /* number of items in cust data list */
896 TLBCustData
* pCustData
; /* linked list to cust data */
897 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
898 int ctTypeDesc
; /* number of items in type desc array */
899 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
900 library. Only used while reading MSFT
902 struct list ref_list
; /* list of ref types in this typelib */
903 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
906 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
907 struct tagITypeLibImpl
*next
, *prev
;
912 static const ITypeLib2Vtbl tlbvt
;
913 static const ITypeCompVtbl tlbtcvt
;
915 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
917 return (ITypeLibImpl
*)((char*)iface
- FIELD_OFFSET(ITypeLibImpl
, lpVtblTypeComp
));
920 /* ITypeLib methods */
921 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
922 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
924 /*======================= ITypeInfo implementation =======================*/
926 /* data for referenced types */
927 typedef struct tagTLBRefType
929 INT index
; /* Type index for internal ref or for external ref
930 it the format is SLTG. -2 indicates to
933 GUID guid
; /* guid of the referenced type */
934 /* if index == TLB_REF_USE_GUID */
936 HREFTYPE reference
; /* The href of this ref */
937 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
938 TLB_REF_INTERNAL for internal refs
939 TLB_REF_NOT_FOUND for broken refs */
944 #define TLB_REF_USE_GUID -2
946 #define TLB_REF_INTERNAL (void*)-2
947 #define TLB_REF_NOT_FOUND (void*)-1
949 /* internal Parameter data */
950 typedef struct tagTLBParDesc
954 TLBCustData
* pCustData
; /* linked list to cust data */
957 /* internal Function data */
958 typedef struct tagTLBFuncDesc
960 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
961 BSTR Name
; /* the name of this function */
962 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
964 int HelpStringContext
;
966 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
968 TLBCustData
* pCustData
; /* linked list to cust data; */
969 struct tagTLBFuncDesc
* next
;
972 /* internal Variable data */
973 typedef struct tagTLBVarDesc
975 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
976 BSTR Name
; /* the name of this variable */
978 int HelpStringContext
; /* FIXME: where? */
981 TLBCustData
* pCustData
;/* linked list to cust data; */
982 struct tagTLBVarDesc
* next
;
985 /* internal implemented interface data */
986 typedef struct tagTLBImplType
988 HREFTYPE hRef
; /* hRef of interface */
989 int implflags
; /* IMPLFLAG_*s */
991 TLBCustData
* pCustData
;/* linked list to custom data; */
992 struct tagTLBImplType
*next
;
995 /* internal TypeInfo data */
996 typedef struct tagITypeInfoImpl
998 const ITypeInfo2Vtbl
*lpVtbl
;
999 const ITypeCompVtbl
*lpVtblTypeComp
;
1001 BOOL no_free_data
; /* don't free data structures */
1002 TYPEATTR TypeAttr
; /* _lots_ of type information. */
1003 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1004 int index
; /* index in this typelib; */
1005 HREFTYPE hreftype
; /* hreftype for app object binding */
1006 /* type libs seem to store the doc strings in ascii
1007 * so why should we do it in unicode?
1012 unsigned long dwHelpContext
;
1013 unsigned long dwHelpStringContext
;
1016 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
1019 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
1021 /* Implemented Interfaces */
1022 TLBImplType
* impltypelist
;
1025 TLBCustData
* pCustData
; /* linked list to cust data; */
1026 struct tagITypeInfoImpl
* next
;
1029 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1031 return (ITypeInfoImpl
*)((char*)iface
- FIELD_OFFSET(ITypeInfoImpl
, lpVtblTypeComp
));
1034 static const ITypeInfo2Vtbl tinfvt
;
1035 static const ITypeCompVtbl tcompvt
;
1037 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void);
1039 typedef struct tagTLBContext
1041 unsigned int oStart
; /* start of TLB in file */
1042 unsigned int pos
; /* current pos */
1043 unsigned int length
; /* total length */
1044 void *mapping
; /* memory mapping */
1045 MSFT_SegDir
* pTblDir
;
1046 ITypeLibImpl
* pLibInfo
;
1050 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
, int offset
);
1055 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1056 if (pTD
->vt
& VT_RESERVED
)
1057 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1058 if (pTD
->vt
& VT_BYREF
)
1059 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1060 if (pTD
->vt
& VT_ARRAY
)
1061 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1062 if (pTD
->vt
& VT_VECTOR
)
1063 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1064 switch(pTD
->vt
& VT_TYPEMASK
) {
1065 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1066 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1067 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1068 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1069 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1070 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1071 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1072 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1073 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1074 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1075 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1076 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1077 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1078 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1079 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1080 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1081 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1082 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1083 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1084 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1085 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1086 pTD
->u
.hreftype
); break;
1087 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1088 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1089 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1090 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1092 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1093 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1095 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1096 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1097 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1100 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1104 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1106 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1107 dump_TypeDesc(&edesc
->tdesc
,buf
);
1108 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1109 MESSAGE("\t\tu.paramdesc.wParamFlags");
1110 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1111 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1112 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1113 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1114 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1115 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1116 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1117 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1118 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1120 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1122 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1123 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1124 MESSAGE("Param %d:\n",i
);
1125 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1127 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1128 switch (funcdesc
->funckind
) {
1129 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1130 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1131 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1132 case FUNC_STATIC
: MESSAGE("static");break;
1133 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1134 default: MESSAGE("unknown");break;
1136 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1137 switch (funcdesc
->invkind
) {
1138 case INVOKE_FUNC
: MESSAGE("func");break;
1139 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1140 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1141 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1143 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1144 switch (funcdesc
->callconv
) {
1145 case CC_CDECL
: MESSAGE("cdecl");break;
1146 case CC_PASCAL
: MESSAGE("pascal");break;
1147 case CC_STDCALL
: MESSAGE("stdcall");break;
1148 case CC_SYSCALL
: MESSAGE("syscall");break;
1151 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1152 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1153 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1155 MESSAGE("\telemdescFunc (return value type):\n");
1156 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1159 static const char * const typekind_desc
[] =
1172 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1175 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1176 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1177 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1180 dump_FUNCDESC(&(pfd
->funcdesc
));
1182 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1183 MESSAGE("\tentry: %s\n", (pfd
->Entry
== (void *)-1) ? "invalid" : debugstr_w(pfd
->Entry
));
1185 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
)
1189 dump_TLBFuncDescOne(pfd
);
1193 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
)
1197 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1202 static void dump_TLBImpLib(const TLBImpLib
*import
)
1204 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1205 debugstr_w(import
->name
));
1206 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1207 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1210 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1214 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1216 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1217 if(ref
->index
== -1)
1218 TRACE_(typelib
)("%s\n", debugstr_guid(&(ref
->guid
)));
1220 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1222 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1224 TRACE_(typelib
)("in lib\n");
1225 dump_TLBImpLib(ref
->pImpTLInfo
);
1230 static void dump_TLBImplType(const TLBImplType
* impl
)
1234 "implementing/inheriting interface hRef = %x implflags %x\n",
1235 impl
->hRef
, impl
->implflags
);
1240 static void dump_Variant(const VARIANT
* pvar
)
1244 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1248 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1249 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1251 TRACE(",%p", V_BYREF(pvar
));
1253 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1255 TRACE(",%p", V_ARRAY(pvar
));
1257 else switch (V_TYPE(pvar
))
1259 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1260 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1261 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1262 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1264 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1266 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1267 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1268 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1269 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1270 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1271 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1272 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1273 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1274 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1275 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1276 V_CY(pvar
).s
.Lo
); break;
1278 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1279 TRACE(",<invalid>");
1281 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1282 st
.wHour
, st
.wMinute
, st
.wSecond
);
1286 case VT_USERDEFINED
:
1288 case VT_NULL
: break;
1289 default: TRACE(",?"); break;
1295 static void dump_DispParms(const DISPPARAMS
* pdp
)
1299 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1301 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1303 TRACE("named args:\n");
1304 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1305 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1308 if (pdp
->cArgs
&& pdp
->rgvarg
)
1311 for (index
= 0; index
< pdp
->cArgs
; index
++)
1312 dump_Variant( &pdp
->rgvarg
[index
] );
1316 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1318 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1319 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1320 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1321 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1322 TRACE("fct:%u var:%u impl:%u\n",
1323 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1324 TRACE("wTypeFlags: 0x%04x\n", pty
->TypeAttr
.wTypeFlags
);
1325 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1326 if (pty
->TypeAttr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(pty
->DllName
));
1328 dump_TLBFuncDesc(pty
->funclist
);
1329 dump_TLBVarDesc(pty
->varlist
);
1330 dump_TLBImplType(pty
->impltypelist
);
1333 static void dump_VARDESC(const VARDESC
*v
)
1335 MESSAGE("memid %d\n",v
->memid
);
1336 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1337 MESSAGE("oInst %d\n",v
->u
.oInst
);
1338 dump_ELEMDESC(&(v
->elemdescVar
));
1339 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1340 MESSAGE("varkind %d\n",v
->varkind
);
1343 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1345 /* VT_LPWSTR is largest type that */
1346 /* may appear in type description*/
1347 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1348 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1349 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1350 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1351 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1352 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1356 static void TLB_abort(void)
1360 static void * TLB_Alloc(unsigned size
)
1363 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1365 ERR("cannot allocate memory\n");
1370 static void TLB_Free(void * ptr
)
1372 HeapFree(GetProcessHeap(), 0, ptr
);
1375 /* returns the size required for a deep copy of a typedesc into a
1377 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1381 if (alloc_initial_space
)
1382 size
+= sizeof(TYPEDESC
);
1388 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1391 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1392 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1398 /* deep copy a typedesc into a flat buffer */
1399 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1404 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1413 dest
->u
.lptdesc
= buffer
;
1414 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1417 dest
->u
.lpadesc
= buffer
;
1418 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1419 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1420 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1426 /* free custom data allocated by MSFT_CustData */
1427 static inline void TLB_FreeCustData(TLBCustData
*pCustData
)
1429 TLBCustData
*pCustDataNext
;
1430 for (; pCustData
; pCustData
= pCustDataNext
)
1432 VariantClear(&pCustData
->data
);
1434 pCustDataNext
= pCustData
->next
;
1435 TLB_Free(pCustData
);
1439 /**********************************************************************
1441 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1443 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
1448 static inline void MSFT_Seek(TLBContext
*pcx
, long where
)
1450 if (where
!= DO_NOT_SEEK
)
1452 where
+= pcx
->oStart
;
1453 if (where
> pcx
->length
)
1456 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1464 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1466 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1467 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1469 MSFT_Seek(pcx
, where
);
1470 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1471 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1476 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1481 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1482 FromLEDWords(buffer
, ret
);
1487 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1492 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1493 FromLEWords(buffer
, ret
);
1498 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1500 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1501 memset(pGuid
,0, sizeof(GUID
));
1504 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1505 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1506 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1507 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1508 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1511 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
1513 MSFT_NameIntro niName
;
1517 ERR_(typelib
)("bad offset %d\n", offset
);
1521 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1522 pcx
->pTblDir
->pNametab
.offset
+offset
);
1524 return niName
.hreftype
;
1527 static BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1530 MSFT_NameIntro niName
;
1532 BSTR bstrName
= NULL
;
1536 ERR_(typelib
)("bad offset %d\n", offset
);
1539 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1540 pcx
->pTblDir
->pNametab
.offset
+offset
);
1541 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1542 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1543 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1544 name
[niName
.namelen
& 0xff]='\0';
1546 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1549 /* no invalid characters in string */
1552 bstrName
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1554 /* don't check for invalid character since this has been done previously */
1555 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, bstrName
, lengthInChars
);
1559 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1563 static BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1570 if(offset
<0) return NULL
;
1571 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1572 if(length
<= 0) return 0;
1573 string
=TLB_Alloc(length
+1);
1574 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1575 string
[length
]='\0';
1577 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1578 string
, -1, NULL
, 0);
1580 /* no invalid characters in string */
1583 bstr
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1585 /* don't check for invalid character since this has been done previously */
1586 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, bstr
, lengthInChars
);
1590 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1594 * read a value and fill a VARIANT structure
1596 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1600 TRACE_(typelib
)("\n");
1602 if(offset
<0) { /* data are packed in here */
1603 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1604 V_I4(pVar
) = offset
& 0x3ffffff;
1607 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1608 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1609 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1610 switch (V_VT(pVar
)){
1611 case VT_EMPTY
: /* FIXME: is this right? */
1612 case VT_NULL
: /* FIXME: is this right? */
1613 case VT_I2
: /* this should not happen */
1624 case VT_VOID
: /* FIXME: is this right? */
1632 case VT_DECIMAL
: /* FIXME: is this right? */
1635 /* pointer types with known behaviour */
1638 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1641 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
1644 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
1646 nullPos
= MSFT_Tell(pcx
);
1647 size
= nullPos
- origPos
;
1648 MSFT_Seek(pcx
, origPos
);
1650 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1651 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1652 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1653 /* FIXME: do we need a AtoW conversion here? */
1654 V_UNION(pVar
, bstrVal
[size
])='\0';
1655 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1659 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1666 case VT_USERDEFINED
:
1672 case VT_STREAMED_OBJECT
:
1673 case VT_STORED_OBJECT
:
1674 case VT_BLOB_OBJECT
:
1679 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1683 if(size
>0) /* (big|small) endian correct? */
1684 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1688 * create a linked list with custom data
1690 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1696 TRACE_(typelib
)("\n");
1700 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1701 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1702 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1703 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1704 /* add new custom data at head of the list */
1705 pNew
->next
=*ppCustData
;
1707 offset
= entry
.next
;
1712 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1716 pTd
->vt
=type
& VT_TYPEMASK
;
1718 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1720 if(pTd
->vt
== VT_USERDEFINED
)
1721 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, pTd
->u
.hreftype
);
1723 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1726 static void MSFT_ResolveReferencedTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, TYPEDESC
*lpTypeDesc
)
1728 /* resolve referenced type if any */
1731 switch (lpTypeDesc
->vt
)
1734 lpTypeDesc
= lpTypeDesc
->u
.lptdesc
;
1738 lpTypeDesc
= & (lpTypeDesc
->u
.lpadesc
->tdescElem
);
1741 case VT_USERDEFINED
:
1742 MSFT_DoRefType(pcx
, pTI
->pTypeLib
,
1743 lpTypeDesc
->u
.hreftype
);
1755 MSFT_DoFuncs(TLBContext
* pcx
,
1760 TLBFuncDesc
** pptfd
)
1763 * member information is stored in a data structure at offset
1764 * indicated by the memoffset field of the typeinfo structure
1765 * There are several distinctive parts.
1766 * The first part starts with a field that holds the total length
1767 * of this (first) part excluding this field. Then follow the records,
1768 * for each member there is one record.
1770 * The first entry is always the length of the record (including this
1772 * The rest of the record depends on the type of the member. If there is
1773 * a field indicating the member type (function, variable, interface, etc)
1774 * I have not found it yet. At this time we depend on the information
1775 * in the type info and the usual order how things are stored.
1777 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1780 * Third is an equal sized array with file offsets to the name entry
1783 * The fourth and last (?) part is an array with offsets to the records
1784 * in the first part of this file segment.
1787 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1788 int recoffset
= offset
+ sizeof(INT
);
1790 char *recbuf
= HeapAlloc(GetProcessHeap(), 0, 0xffff);
1791 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1792 TLBFuncDesc
*ptfd_prev
= NULL
;
1794 TRACE_(typelib
)("\n");
1796 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1798 for ( i
= 0; i
< cFuncs
; i
++ )
1800 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1802 /* name, eventually add to a hash table */
1803 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1804 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1806 /* nameoffset is sometimes -1 on the second half of a propget/propput
1807 * pair of functions */
1808 if ((nameoffset
== -1) && (i
> 0))
1809 (*pptfd
)->Name
= SysAllocString(ptfd_prev
->Name
);
1811 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1813 /* read the function information record */
1814 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1816 reclength
&= 0xffff;
1818 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1820 /* do the attributes */
1821 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1824 if ( nrattributes
> 0 )
1826 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1828 if ( nrattributes
> 1 )
1830 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1831 pFuncRec
->OptAttr
[1]) ;
1833 if ( nrattributes
> 2 )
1835 if ( pFuncRec
->FKCCIC
& 0x2000 )
1837 if (HIWORD(pFuncRec
->OptAttr
[2]) != 0)
1838 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec
->OptAttr
[2]);
1839 (*pptfd
)->Entry
= (BSTR
)pFuncRec
->OptAttr
[2];
1843 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1844 pFuncRec
->OptAttr
[2]);
1846 if( nrattributes
> 5 )
1848 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1850 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1853 pFuncRec
->OptAttr
[6],
1854 &(*pptfd
)->pCustData
);
1860 (*pptfd
)->Entry
= (BSTR
)-1;
1865 /* fill the FuncDesc Structure */
1866 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1867 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1869 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1870 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1871 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1872 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1873 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1874 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1875 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1879 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1881 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
);
1883 /* do the parameters/arguments */
1884 if(pFuncRec
->nrargs
)
1887 MSFT_ParameterInfo paraminfo
;
1889 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1890 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1892 (*pptfd
)->pParamDesc
=
1893 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1895 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1896 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1898 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1900 ELEMDESC
*elemdesc
= &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1907 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1910 if (paraminfo
.oName
== -1)
1911 /* this occurs for [propput] or [propget] methods, so
1912 * we should just set the name of the parameter to the
1913 * name of the method. */
1914 (*pptfd
)->pParamDesc
[j
].Name
= SysAllocString((*pptfd
)->Name
);
1916 (*pptfd
)->pParamDesc
[j
].Name
=
1917 MSFT_ReadName( pcx
, paraminfo
.oName
);
1918 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w((*pptfd
)->pParamDesc
[j
].Name
));
1920 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
1923 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
1924 (pFuncRec
->FKCCIC
& 0x1000) )
1926 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1928 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1930 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
1932 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1933 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1935 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1939 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
1941 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1944 pFuncRec
->OptAttr
[7+j
],
1945 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1948 /* SEEK value = jump to offset,
1949 * from there jump to the end of record,
1950 * go back by (j-1) arguments
1952 MSFT_ReadLEDWords( ¶minfo
,
1953 sizeof(MSFT_ParameterInfo
), pcx
,
1954 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1955 * sizeof(MSFT_ParameterInfo
)));
1959 /* scode is not used: archaic win16 stuff FIXME: right? */
1960 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1961 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1964 pptfd
= & ((*pptfd
)->next
);
1965 recoffset
+= reclength
;
1967 HeapFree(GetProcessHeap(), 0, recbuf
);
1970 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1971 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1973 int infolen
, nameoffset
, reclength
;
1975 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1979 TRACE_(typelib
)("\n");
1981 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1982 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1983 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1984 recoffset
+= offset
+sizeof(INT
);
1985 for(i
=0;i
<cVars
;i
++){
1986 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1987 /* name, eventually add to a hash table */
1988 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1989 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1990 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1991 /* read the variable information record */
1992 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1994 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1996 if(reclength
>(6*sizeof(INT
)) )
1997 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1998 if(reclength
>(7*sizeof(INT
)) )
1999 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
2000 if(reclength
>(8*sizeof(INT
)) )
2001 if(reclength
>(9*sizeof(INT
)) )
2002 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
2003 /* fill the VarDesc Structure */
2004 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
2005 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2006 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
2007 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
2008 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2009 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
2010 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2011 if(pVarRec
->VarKind
== VAR_CONST
){
2012 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
2013 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
2014 pVarRec
->OffsValue
, pcx
);
2016 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2017 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptvd
)->vardesc
.elemdescVar
.tdesc
);
2018 pptvd
=&((*pptvd
)->next
);
2019 recoffset
+= reclength
;
2022 /* fill in data for a hreftype (offset). When the referenced type is contained
2023 * in the typelib, it's just an (file) offset in the type info base dir.
2024 * If comes from import, it's an offset+1 in the ImpInfo table
2026 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
,
2031 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2033 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
2035 if(ref
->reference
== offset
) return;
2038 ref
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref
));
2039 list_add_tail(&pTL
->ref_list
, &ref
->entry
);
2041 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2042 /* external typelib */
2043 MSFT_ImpInfo impinfo
;
2044 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
2046 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2048 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2049 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2050 while (pImpLib
){ /* search the known offsets of all import libraries */
2051 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
2052 pImpLib
=pImpLib
->next
;
2055 ref
->reference
= offset
;
2056 ref
->pImpTLInfo
= pImpLib
;
2057 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2058 MSFT_ReadGuid(&ref
->guid
, impinfo
.oGuid
, pcx
);
2059 TRACE("importing by guid %s\n", debugstr_guid(&ref
->guid
));
2060 ref
->index
= TLB_REF_USE_GUID
;
2062 ref
->index
= impinfo
.oGuid
;
2064 ERR("Cannot find a reference\n");
2065 ref
->reference
= -1;
2066 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2069 /* in this typelib */
2070 ref
->index
= MSFT_HREFTYPE_INDEX(offset
);
2071 ref
->reference
= offset
;
2072 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
2076 /* process Implemented Interfaces of a com class */
2077 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2081 MSFT_RefRecord refrec
;
2082 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
2084 TRACE_(typelib
)("\n");
2086 for(i
=0;i
<count
;i
++){
2087 if(offset
<0) break; /* paranoia */
2088 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
2089 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2090 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, refrec
.reftype
);
2091 (*ppImpl
)->hRef
= refrec
.reftype
;
2092 (*ppImpl
)->implflags
=refrec
.flags
;
2093 (*ppImpl
)->ctCustData
=
2094 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
2095 offset
=refrec
.onext
;
2096 ppImpl
=&((*ppImpl
)->next
);
2100 * process a typeinfo record
2102 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2105 ITypeLibImpl
* pLibInfo
)
2107 MSFT_TypeInfoBase tiBase
;
2108 ITypeInfoImpl
*ptiRet
;
2110 TRACE_(typelib
)("count=%u\n", count
);
2112 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
2113 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2114 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2116 /* this is where we are coming from */
2117 ptiRet
->pTypeLib
= pLibInfo
;
2118 ptiRet
->index
=count
;
2119 /* fill in the typeattr fields */
2121 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2122 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2123 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2124 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2125 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2126 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2127 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2128 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2129 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2130 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2131 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2132 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2133 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2134 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2135 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2136 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2139 /* IDLDESC idldescType; *//* never saw this one != zero */
2141 /* name, eventually add to a hash table */
2142 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2143 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2144 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2146 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2147 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2148 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2150 if (ptiRet
->TypeAttr
.typekind
== TKIND_MODULE
)
2151 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2153 /* note: InfoType's Help file and HelpStringDll come from the containing
2154 * library. Further HelpString and Docstring appear to be the same thing :(
2157 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2158 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2159 ptiRet
->TypeAttr
.cVars
,
2160 tiBase
.memoffset
, & ptiRet
->funclist
);
2162 if(ptiRet
->TypeAttr
.cVars
>0 )
2163 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2164 ptiRet
->TypeAttr
.cVars
,
2165 tiBase
.memoffset
, & ptiRet
->varlist
);
2166 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2167 switch(ptiRet
->TypeAttr
.typekind
)
2170 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2173 case TKIND_DISPATCH
:
2174 /* This is not -1 when the interface is a non-base dual interface or
2175 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2176 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2180 if (tiBase
.datatype1
!= -1)
2182 ptiRet
->impltypelist
= TLB_Alloc(sizeof(TLBImplType
));
2183 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2184 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2188 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2189 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2190 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2195 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2197 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2198 debugstr_w(ptiRet
->Name
),
2199 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2200 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2205 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2206 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2207 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2210 static ITypeLibImpl
*tlb_cache_first
;
2211 static CRITICAL_SECTION cache_section
;
2212 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2214 0, 0, &cache_section
,
2215 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2216 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2218 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2221 typedef struct TLB_PEFile
2223 const IUnknownVtbl
*lpvtbl
;
2226 HRSRC typelib_resource
;
2227 HGLOBAL typelib_global
;
2228 LPVOID typelib_base
;
2231 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2233 if (IsEqualIID(riid
, &IID_IUnknown
))
2236 IUnknown_AddRef(iface
);
2240 return E_NOINTERFACE
;
2243 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2245 TLB_PEFile
*This
= (TLB_PEFile
*)iface
;
2246 return InterlockedIncrement(&This
->refs
);
2249 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2251 TLB_PEFile
*This
= (TLB_PEFile
*)iface
;
2252 ULONG refs
= InterlockedDecrement(&This
->refs
);
2255 if (This
->typelib_global
)
2256 FreeResource(This
->typelib_global
);
2258 FreeLibrary(This
->dll
);
2259 HeapFree(GetProcessHeap(), 0, This
);
2264 static const IUnknownVtbl TLB_PEFile_Vtable
=
2266 TLB_PEFile_QueryInterface
,
2271 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2275 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2277 return E_OUTOFMEMORY
;
2279 This
->lpvtbl
= &TLB_PEFile_Vtable
;
2282 This
->typelib_resource
= NULL
;
2283 This
->typelib_global
= NULL
;
2284 This
->typelib_base
= NULL
;
2286 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2287 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2291 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2292 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2293 if (This
->typelib_resource
)
2295 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2296 if (This
->typelib_global
)
2298 This
->typelib_base
= LockResource(This
->typelib_global
);
2300 if (This
->typelib_base
)
2302 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2303 *ppBase
= This
->typelib_base
;
2304 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2311 TLB_PEFile_Release((IUnknown
*)&This
->lpvtbl
);
2312 return TYPE_E_CANTLOADLIBRARY
;
2316 typedef struct TLB_Mapping
2318 const IUnknownVtbl
*lpvtbl
;
2322 LPVOID typelib_base
;
2325 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2327 if (IsEqualIID(riid
, &IID_IUnknown
))
2330 IUnknown_AddRef(iface
);
2334 return E_NOINTERFACE
;
2337 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
2339 TLB_Mapping
*This
= (TLB_Mapping
*)iface
;
2340 return InterlockedIncrement(&This
->refs
);
2343 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
2345 TLB_Mapping
*This
= (TLB_Mapping
*)iface
;
2346 ULONG refs
= InterlockedDecrement(&This
->refs
);
2349 if (This
->typelib_base
)
2350 UnmapViewOfFile(This
->typelib_base
);
2352 CloseHandle(This
->mapping
);
2353 if (This
->file
!= INVALID_HANDLE_VALUE
)
2354 CloseHandle(This
->file
);
2355 HeapFree(GetProcessHeap(), 0, This
);
2360 static const IUnknownVtbl TLB_Mapping_Vtable
=
2362 TLB_Mapping_QueryInterface
,
2367 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2371 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2373 return E_OUTOFMEMORY
;
2375 This
->lpvtbl
= &TLB_Mapping_Vtable
;
2377 This
->file
= INVALID_HANDLE_VALUE
;
2378 This
->mapping
= NULL
;
2379 This
->typelib_base
= NULL
;
2381 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
2382 if (INVALID_HANDLE_VALUE
!= This
->file
)
2384 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2387 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
2388 if(This
->typelib_base
)
2390 /* retrieve file size */
2391 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
2392 *ppBase
= This
->typelib_base
;
2393 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2399 IUnknown_Release((IUnknown
*)&This
->lpvtbl
);
2400 return TYPE_E_CANTLOADLIBRARY
;
2403 /****************************************************************************
2406 * find the type of the typelib file and map the typelib resource into
2409 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2410 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2411 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
2413 ITypeLibImpl
*entry
;
2416 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
2417 LPVOID pBase
= NULL
;
2418 DWORD dwTLBLength
= 0;
2419 IUnknown
*pFile
= NULL
;
2423 index_str
= strrchrW(pszFileName
, '\\');
2424 if(index_str
&& *++index_str
!= '\0')
2427 long idx
= strtolW(index_str
, &end_ptr
, 10);
2428 if(*end_ptr
== '\0')
2430 int str_len
= index_str
- pszFileName
- 1;
2432 file
= HeapAlloc(GetProcessHeap(), 0, (str_len
+ 1) * sizeof(WCHAR
));
2433 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
2438 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
2440 if(strchrW(file
, '\\'))
2442 lstrcpyW(pszPath
, file
);
2446 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
2447 pszPath
[len
] = '\\';
2448 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
2452 if(file
!= pszFileName
) HeapFree(GetProcessHeap(), 0, file
);
2454 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
2456 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2457 EnterCriticalSection(&cache_section
);
2458 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2460 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
2462 TRACE("cache hit\n");
2463 *ppTypeLib
= (ITypeLib2
*)entry
;
2464 ITypeLib_AddRef(*ppTypeLib
);
2465 LeaveCriticalSection(&cache_section
);
2469 LeaveCriticalSection(&cache_section
);
2471 /* now actually load and parse the typelib */
2473 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2474 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2475 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
2478 if (dwTLBLength
>= 4)
2480 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2481 if (dwSignature
== MSFT_SIGNATURE
)
2482 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2483 else if (dwSignature
== SLTG_SIGNATURE
)
2484 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2487 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
2488 ret
= TYPE_E_CANTLOADLIBRARY
;
2492 ret
= TYPE_E_CANTLOADLIBRARY
;
2493 IUnknown_Release(pFile
);
2497 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2499 TRACE("adding to cache\n");
2500 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath
)+1) * sizeof(WCHAR
));
2501 lstrcpyW(impl
->path
, pszPath
);
2502 /* We should really canonicalise the path here. */
2503 impl
->index
= index
;
2505 /* FIXME: check if it has added already in the meantime */
2506 EnterCriticalSection(&cache_section
);
2507 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2509 tlb_cache_first
= impl
;
2510 LeaveCriticalSection(&cache_section
);
2513 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
2518 /*================== ITypeLib(2) Methods ===================================*/
2520 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
2522 ITypeLibImpl
* pTypeLibImpl
;
2524 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2525 if (!pTypeLibImpl
) return NULL
;
2527 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2528 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2529 pTypeLibImpl
->ref
= 1;
2531 list_init(&pTypeLibImpl
->ref_list
);
2532 pTypeLibImpl
->dispatch_href
= -1;
2534 return pTypeLibImpl
;
2537 /****************************************************************************
2538 * ITypeLib2_Constructor_MSFT
2540 * loading an MSFT typelib from an in-memory image
2542 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2546 MSFT_Header tlbHeader
;
2547 MSFT_SegDir tlbSegDir
;
2548 ITypeLibImpl
* pTypeLibImpl
;
2550 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
2552 pTypeLibImpl
= TypeLibImpl_Constructor();
2553 if (!pTypeLibImpl
) return NULL
;
2555 /* get pointer to beginning of typelib data */
2559 cx
.pLibInfo
= pTypeLibImpl
;
2560 cx
.length
= dwTLBLength
;
2563 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2564 TRACE_(typelib
)("header:\n");
2565 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2566 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2567 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2570 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
2572 /* there is a small amount of information here until the next important
2574 * the segment directory . Try to calculate the amount of data */
2575 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2577 /* now read the segment directory */
2578 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2579 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2580 cx
.pTblDir
= &tlbSegDir
;
2582 /* just check two entries */
2583 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2585 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2586 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2590 /* now fill our internal data */
2591 /* TLIBATTR fields */
2592 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2594 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2595 /* Windows seems to have zero here, is this correct? */
2596 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2597 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader
.lcid
),0),0);
2599 pTypeLibImpl
->LibAttr
.lcid
= 0;
2601 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2602 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2603 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2604 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2606 /* name, eventually add to a hash table */
2607 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2610 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2611 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2613 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2616 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2617 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2620 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2623 if(tlbHeader
.CustomDataOffset
>= 0)
2625 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2628 /* fill in type descriptions */
2629 if(tlbSegDir
.pTypdescTab
.length
> 0)
2631 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2633 pTypeLibImpl
->ctTypeDesc
= cTD
;
2634 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2635 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2638 /* FIXME: add several sanity checks here */
2639 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2640 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2642 /* FIXME: check safearray */
2644 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2646 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2648 else if(td
[0] == VT_CARRAY
)
2650 /* array descr table here */
2651 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2653 else if(td
[0] == VT_USERDEFINED
)
2655 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2657 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2660 /* second time around to fill the array subscript info */
2663 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2664 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2666 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2667 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2670 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2672 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2674 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2676 for(j
= 0; j
<td
[2]; j
++)
2678 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2679 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2680 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2681 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2686 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2687 ERR("didn't find array description data\n");
2692 /* imported type libs */
2693 if(tlbSegDir
.pImpFiles
.offset
>0)
2695 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2696 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2699 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2704 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2705 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2706 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2708 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2709 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2710 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2711 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2714 name
= TLB_Alloc(size
+1);
2715 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2716 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
2717 (*ppImpLib
)->name
= TLB_Alloc(len
* sizeof(WCHAR
));
2718 MultiByteToWideChar(CP_ACP
, 0, name
, -1, (*ppImpLib
)->name
, len
);
2721 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2722 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2724 ppImpLib
= &(*ppImpLib
)->next
;
2728 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
2729 if(pTypeLibImpl
->dispatch_href
!= -1)
2730 MSFT_DoRefType(&cx
, pTypeLibImpl
, pTypeLibImpl
->dispatch_href
);
2733 if(tlbHeader
.nrtypeinfos
>= 0 )
2735 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2736 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2739 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
2741 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2743 ppTI
= &((*ppTI
)->next
);
2744 (pTypeLibImpl
->TypeInfoCount
)++;
2748 TRACE("(%p)\n", pTypeLibImpl
);
2749 return (ITypeLib2
*) pTypeLibImpl
;
2753 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
2759 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2760 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2761 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2762 ret
= SysAllocString(nameW
);
2763 HeapFree(GetProcessHeap(), 0, nameW
);
2767 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
2773 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2774 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2778 guid
->Data4
[0] = s
>> 8;
2779 guid
->Data4
[1] = s
& 0xff;
2782 for(i
= 0; i
< 6; i
++) {
2783 memcpy(b
, str
+ 24 + 2 * i
, 2);
2784 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2789 static WORD
SLTG_ReadString(const char *ptr
, BSTR
*pBstr
)
2796 bytelen
= *(const WORD
*)ptr
;
2797 if(bytelen
== 0xffff) return 2;
2798 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2799 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2800 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2801 *pBstr
= SysAllocStringLen(nameW
, len
);
2802 HeapFree(GetProcessHeap(), 0, nameW
);
2806 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
2811 bytelen
= *(const WORD
*)ptr
;
2812 if(bytelen
== 0xffff) return 2;
2813 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2814 memcpy(*str
, ptr
+ 2, bytelen
);
2815 (*str
)[bytelen
] = '\0';
2819 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2821 char *ptr
= pLibBlk
;
2824 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2825 FIXME("libblk magic = %04x\n", w
);
2830 if((w
= *(WORD
*)ptr
) != 0xffff) {
2831 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2836 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2838 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2840 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2843 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2846 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
2847 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
2849 pTypeLibImpl
->LibAttr
.lcid
= 0;
2852 ptr
+= 4; /* skip res12 */
2854 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2857 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2860 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2863 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2864 ptr
+= sizeof(GUID
);
2866 return ptr
- (char*)pLibBlk
;
2869 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
2874 } sltg_ref_lookup_t
;
2876 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
2877 HREFTYPE
*typelib_ref
)
2879 if(typeinfo_ref
< table
->num
)
2881 *typelib_ref
= table
->refs
[typeinfo_ref
];
2885 ERR_(typelib
)("Unable to find reference\n");
2890 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
2895 if((*pType
& 0xe00) == 0xe00) {
2897 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2899 pTD
= pTD
->u
.lptdesc
;
2901 switch(*pType
& 0x3f) {
2904 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2906 pTD
= pTD
->u
.lptdesc
;
2909 case VT_USERDEFINED
:
2910 pTD
->vt
= VT_USERDEFINED
;
2911 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
2917 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2920 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2922 pTD
->vt
= VT_CARRAY
;
2923 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2925 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2926 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2927 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2928 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2930 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2936 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2940 pTD
->vt
= VT_SAFEARRAY
;
2941 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2943 pTD
= pTD
->u
.lptdesc
;
2947 pTD
->vt
= *pType
& 0x3f;
2956 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
2957 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
2959 /* Handle [in/out] first */
2960 if((*pType
& 0xc000) == 0xc000)
2961 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2962 else if(*pType
& 0x8000)
2963 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2964 else if(*pType
& 0x4000)
2965 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2967 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2970 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2973 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2975 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
2979 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
2984 TLBRefType
*ref_type
;
2985 sltg_ref_lookup_t
*table
;
2986 HREFTYPE typelib_ref
;
2988 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2989 FIXME("Ref magic = %x\n", pRef
->magic
);
2992 name
= ( (char*)pRef
->names
+ pRef
->number
);
2994 table
= HeapAlloc(GetProcessHeap(), 0, sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
2995 table
->num
= pRef
->number
>> 3;
2997 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
2999 /* We don't want the first href to be 0 */
3000 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3002 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3004 unsigned int lib_offs
, type_num
;
3006 ref_type
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref_type
));
3008 name
+= SLTG_ReadStringA(name
, &refname
);
3009 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3010 FIXME_(typelib
)("Can't sscanf ref\n");
3011 if(lib_offs
!= 0xffff) {
3012 TLBImpLib
**import
= &pTL
->pImpLibs
;
3015 if((*import
)->offset
== lib_offs
)
3017 import
= &(*import
)->next
;
3020 char fname
[MAX_PATH
+1];
3023 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3025 (*import
)->offset
= lib_offs
;
3026 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
3028 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3029 &(*import
)->wVersionMajor
,
3030 &(*import
)->wVersionMinor
,
3031 &(*import
)->lcid
, fname
) != 4) {
3032 FIXME_(typelib
)("can't sscanf ref %s\n",
3033 pNameTable
+ lib_offs
+ 40);
3035 len
= strlen(fname
);
3036 if(fname
[len
-1] != '#')
3037 FIXME("fname = %s\n", fname
);
3038 fname
[len
-1] = '\0';
3039 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
3041 ref_type
->pImpTLInfo
= *import
;
3043 /* Store a reference to IDispatch */
3044 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&(*import
)->guid
, &IID_StdOle
) && type_num
== 4)
3045 pTL
->dispatch_href
= typelib_ref
;
3047 } else { /* internal ref */
3048 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3050 ref_type
->reference
= typelib_ref
;
3051 ref_type
->index
= type_num
;
3053 HeapFree(GetProcessHeap(), 0, refname
);
3054 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3056 table
->refs
[ref
] = typelib_ref
;
3059 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3060 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3061 dump_TLBRefType(pTL
);
3065 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3066 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3068 SLTG_ImplInfo
*info
;
3069 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
3070 /* I don't really get this structure, usually it's 0x16 bytes
3071 long, but iuser.tlb contains some that are 0x18 bytes long.
3072 That's ok because we can use the next ptr to jump to the next
3073 one. But how do we know the length of the last one? The WORD
3074 at offs 0x8 might be the clue. For now I'm just assuming that
3075 the last one is the regular 0x16 bytes. */
3077 info
= (SLTG_ImplInfo
*)pBlk
;
3079 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3080 sizeof(**ppImplType
));
3081 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &(*ppImplType
)->hRef
);
3082 (*ppImplType
)->implflags
= info
->impltypeflags
;
3083 pTI
->TypeAttr
.cImplTypes
++;
3084 ppImplType
= &(*ppImplType
)->next
;
3086 if(info
->next
== 0xffff)
3089 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3090 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3092 info
++; /* see comment at top of function */
3096 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
3097 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3099 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
3100 BSTR bstrPrevName
= NULL
;
3101 SLTG_Variable
*pItem
;
3105 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
3106 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++) {
3108 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3109 sizeof(**ppVarDesc
));
3110 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
3112 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
3113 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
3114 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
3118 if (pItem
->name
== 0xfffe)
3119 (*ppVarDesc
)->Name
= SysAllocString(bstrPrevName
);
3121 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3123 TRACE_(typelib
)("name: %s\n", debugstr_w((*ppVarDesc
)->Name
));
3124 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
3125 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
3127 if(pItem
->flags
& 0x02)
3128 pType
= &pItem
->type
;
3130 pType
= (WORD
*)(pBlk
+ pItem
->type
);
3132 if (pItem
->flags
& ~0xda)
3133 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
3135 SLTG_DoElem(pType
, pBlk
,
3136 &(*ppVarDesc
)->vardesc
.elemdescVar
, ref_lookup
);
3138 if (TRACE_ON(typelib
)) {
3140 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
3141 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
3144 if (pItem
->flags
& 0x40) {
3145 TRACE_(typelib
)("VAR_DISPATCH\n");
3146 (*ppVarDesc
)->vardesc
.varkind
= VAR_DISPATCH
;
3148 else if (pItem
->flags
& 0x10) {
3149 TRACE_(typelib
)("VAR_CONST\n");
3150 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
3151 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
3153 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
3154 if (pItem
->flags
& 0x08)
3155 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) = pItem
->byte_offs
;
3157 switch ((*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
)
3163 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
3164 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
3165 BSTR str
= SysAllocStringLen(NULL
, alloc_len
);
3166 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
3167 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_BSTR
;
3168 V_BSTR((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = str
;
3175 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
3176 *(INT
*)(pBlk
+ pItem
->byte_offs
);
3179 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
);
3184 TRACE_(typelib
)("VAR_PERINSTANCE\n");
3185 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
3186 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
3189 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
3190 (*ppVarDesc
)->vardesc
.wVarFlags
= pItem
->varflags
;
3192 if (pItem
->flags
& 0x80)
3193 (*ppVarDesc
)->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
3195 bstrPrevName
= (*ppVarDesc
)->Name
;
3196 ppVarDesc
= &((*ppVarDesc
)->next
);
3198 pTI
->TypeAttr
.cVars
= cVars
;
3201 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
3202 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3204 SLTG_Function
*pFunc
;
3206 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
3208 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
;
3209 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++) {
3214 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3215 sizeof(**ppFuncDesc
));
3217 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
3218 case SLTG_FUNCTION_MAGIC
:
3219 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
3221 case SLTG_DISPATCH_FUNCTION_MAGIC
:
3222 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_DISPATCH
;
3224 case SLTG_STATIC_FUNCTION_MAGIC
:
3225 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_STATIC
;
3228 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
3229 HeapFree(GetProcessHeap(), 0, *ppFuncDesc
);
3233 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
3235 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
3236 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
3237 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
3238 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
3239 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
3240 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
3242 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
3243 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
3245 if(pFunc
->retnextopt
& 0x80)
3246 pType
= &pFunc
->rettype
;
3248 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
3250 SLTG_DoElem(pType
, pBlk
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
, ref_lookup
);
3252 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
3253 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3254 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
3255 (*ppFuncDesc
)->pParamDesc
=
3256 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3257 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
3259 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
3261 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
3262 char *paramName
= pNameTable
+ *pArg
;
3264 /* If arg type follows then paramName points to the 2nd
3265 letter of the name, else the next WORD is an offset to
3266 the arg type and paramName points to the first letter.
3267 So let's take one char off paramName and see if we're
3268 pointing at an alpha-numeric char. However if *pArg is
3269 0xffff or 0xfffe then the param has no name, the former
3270 meaning that the next WORD is the type, the latter
3271 meaning that the next WORD is an offset to the type. */
3276 else if(*pArg
== 0xfffe) {
3280 else if(paramName
[-1] && !isalnum(paramName
[-1]))
3285 if(HaveOffs
) { /* the next word is an offset to type */
3286 pType
= (WORD
*)(pBlk
+ *pArg
);
3287 SLTG_DoElem(pType
, pBlk
,
3288 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3293 pArg
= SLTG_DoElem(pArg
, pBlk
,
3294 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3297 /* Are we an optional param ? */
3298 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
3299 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
3300 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
3303 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
3304 TLB_MultiByteToBSTR(paramName
);
3308 ppFuncDesc
= &((*ppFuncDesc
)->next
);
3309 if(pFunc
->next
== 0xffff) break;
3311 pTI
->TypeAttr
.cFuncs
= cFuncs
;
3314 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
3315 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3316 SLTG_TypeInfoTail
*pTITail
)
3319 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3321 if(pTIHeader
->href_table
!= 0xffffffff) {
3322 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3328 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3329 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
3331 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3335 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
3336 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3337 const SLTG_TypeInfoTail
*pTITail
)
3340 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3342 if(pTIHeader
->href_table
!= 0xffffffff) {
3343 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3349 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3350 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
3353 if (pTITail
->funcs_off
!= 0xffff)
3354 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3356 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3358 if (TRACE_ON(typelib
))
3359 dump_TLBFuncDesc(pTI
->funclist
);
3362 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
3363 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3364 const SLTG_TypeInfoTail
*pTITail
)
3366 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3369 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3370 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3371 const SLTG_TypeInfoTail
*pTITail
)
3374 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3376 if (pTITail
->simple_alias
) {
3377 /* if simple alias, no more processing required */
3378 pTI
->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3382 if(pTIHeader
->href_table
!= 0xffffffff) {
3383 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3387 /* otherwise it is an offset to a type */
3388 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
3390 SLTG_DoType(pType
, pBlk
, &pTI
->TypeAttr
.tdescAlias
, ref_lookup
);
3392 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3395 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3396 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3397 const SLTG_TypeInfoTail
*pTITail
)
3399 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3400 if (pTIHeader
->href_table
!= 0xffffffff)
3401 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3404 if (pTITail
->vars_off
!= 0xffff)
3405 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3407 if (pTITail
->funcs_off
!= 0xffff)
3408 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3410 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3411 * of dispinterface functions including the IDispatch ones, so
3412 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3413 pTI
->TypeAttr
.cbSizeVft
= pTI
->TypeAttr
.cFuncs
* sizeof(void *);
3415 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3416 if (TRACE_ON(typelib
))
3417 dump_TLBFuncDesc(pTI
->funclist
);
3420 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3421 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3422 const SLTG_TypeInfoTail
*pTITail
)
3424 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3427 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
3428 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3429 const SLTG_TypeInfoTail
*pTITail
)
3431 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3432 if (pTIHeader
->href_table
!= 0xffffffff)
3433 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3436 if (pTITail
->vars_off
!= 0xffff)
3437 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3439 if (pTITail
->funcs_off
!= 0xffff)
3440 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3441 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3442 if (TRACE_ON(typelib
))
3446 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3447 managable copy of it into this */
3460 } SLTG_InternalOtherTypeInfo
;
3462 /****************************************************************************
3463 * ITypeLib2_Constructor_SLTG
3465 * loading a SLTG typelib from an in-memory image
3467 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3469 ITypeLibImpl
*pTypeLibImpl
;
3470 SLTG_Header
*pHeader
;
3471 SLTG_BlkEntry
*pBlkEntry
;
3475 LPVOID pBlk
, pFirstBlk
;
3476 SLTG_LibBlk
*pLibBlk
;
3477 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3478 char *pAfterOTIBlks
= NULL
;
3479 char *pNameTable
, *ptr
;
3482 ITypeInfoImpl
**ppTypeInfoImpl
;
3484 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3487 pTypeLibImpl
= TypeLibImpl_Constructor();
3488 if (!pTypeLibImpl
) return NULL
;
3492 TRACE_(typelib
)("header:\n");
3493 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
3494 pHeader
->nrOfFileBlks
);
3495 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3496 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
3497 pHeader
->SLTG_magic
);
3501 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3502 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3504 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3505 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3507 /* Next we have a magic block */
3508 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3510 /* Let's see if we're still in sync */
3511 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3512 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3513 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3516 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3517 sizeof(SLTG_DIR_MAGIC
))) {
3518 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
3522 pIndex
= (SLTG_Index
*)(pMagic
+1);
3524 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3526 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
3528 /* We'll set up a ptr to the main library block, which is the last one. */
3530 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3531 pBlkEntry
[order
].next
!= 0;
3532 order
= pBlkEntry
[order
].next
- 1, i
++) {
3533 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3537 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3539 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3544 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3546 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3547 sizeof(*pOtherTypeInfoBlks
) *
3548 pTypeLibImpl
->TypeInfoCount
);
3551 ptr
= (char*)pLibBlk
+ len
;
3553 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3557 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3559 w
= *(WORD
*)(ptr
+ 2);
3562 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3564 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3565 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3567 w
= *(WORD
*)(ptr
+ 4 + len
);
3569 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3571 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3573 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3574 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3576 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3577 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3578 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3580 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3582 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3585 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3586 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3587 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3588 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3589 len
+= sizeof(SLTG_OtherTypeInfo
);
3593 pAfterOTIBlks
= ptr
;
3595 /* Skip this WORD and get the next DWORD */
3596 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3598 /* Now add this to pLibBLk look at what we're pointing at and
3599 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3600 dust and we should be pointing at the beginning of the name
3603 pNameTable
= (char*)pLibBlk
+ len
;
3605 switch(*(WORD
*)pNameTable
) {
3612 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3616 pNameTable
+= 0x216;
3620 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3622 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3625 /* Hopefully we now have enough ptrs set up to actually read in
3626 some TypeInfos. It's not clear which order to do them in, so
3627 I'll just follow the links along the BlkEntry chain and read
3628 them in the order in which they are in the file */
3630 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3632 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3633 pBlkEntry
[order
].next
!= 0;
3634 order
= pBlkEntry
[order
].next
- 1, i
++) {
3636 SLTG_TypeInfoHeader
*pTIHeader
;
3637 SLTG_TypeInfoTail
*pTITail
;
3638 SLTG_MemberHeader
*pMemHeader
;
3640 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3641 pOtherTypeInfoBlks
[i
].index_name
)) {
3642 FIXME_(typelib
)("Index strings don't match\n");
3647 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3648 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3651 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3652 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3653 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
3655 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3656 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3657 (*ppTypeInfoImpl
)->index
= i
;
3658 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3659 pOtherTypeInfoBlks
[i
].name_offs
+
3661 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3662 (*ppTypeInfoImpl
)->TypeAttr
.guid
= pOtherTypeInfoBlks
[i
].uuid
;
3663 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3664 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3665 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3666 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3667 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3669 if((pTIHeader
->typeflags1
& 7) != 2)
3670 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3671 if(pTIHeader
->typeflags3
!= 2)
3672 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3674 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3675 debugstr_w((*ppTypeInfoImpl
)->Name
),
3676 typekind_desc
[pTIHeader
->typekind
],
3677 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3678 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3680 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
3682 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
3684 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3685 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3686 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3688 switch(pTIHeader
->typekind
) {
3690 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3691 pTIHeader
, pTITail
);
3695 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3696 pTIHeader
, pTITail
);
3699 case TKIND_INTERFACE
:
3700 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3701 pTIHeader
, pTITail
);
3705 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3706 pTIHeader
, pTITail
);
3710 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3711 pTIHeader
, pTITail
);
3714 case TKIND_DISPATCH
:
3715 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3716 pTIHeader
, pTITail
);
3720 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3721 pTIHeader
, pTITail
);
3725 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3730 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3731 but we've already set those */
3732 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3747 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3748 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3751 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3752 FIXME("Somehow processed %d TypeInfos\n", i
);
3756 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3757 return (ITypeLib2
*)pTypeLibImpl
;
3760 /* ITypeLib::QueryInterface
3762 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3767 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3769 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3772 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3773 IsEqualIID(riid
,&IID_ITypeLib
)||
3774 IsEqualIID(riid
,&IID_ITypeLib2
))
3781 ITypeLib2_AddRef(iface
);
3782 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3785 TRACE("-- Interface: E_NOINTERFACE\n");
3786 return E_NOINTERFACE
;
3791 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3793 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3794 ULONG ref
= InterlockedIncrement(&This
->ref
);
3796 TRACE("(%p)->ref was %u\n",This
, ref
- 1);
3801 /* ITypeLib::Release
3803 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3805 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3806 ULONG ref
= InterlockedDecrement(&This
->ref
);
3808 TRACE("(%p)->(%u)\n",This
, ref
);
3812 TLBImpLib
*pImpLib
, *pImpLibNext
;
3813 TLBCustData
*pCustData
, *pCustDataNext
;
3814 TLBRefType
*ref_type
;
3818 /* remove cache entry */
3821 TRACE("removing from cache list\n");
3822 EnterCriticalSection(&cache_section
);
3823 if (This
->next
) This
->next
->prev
= This
->prev
;
3824 if (This
->prev
) This
->prev
->next
= This
->next
;
3825 else tlb_cache_first
= This
->next
;
3826 LeaveCriticalSection(&cache_section
);
3827 HeapFree(GetProcessHeap(), 0, This
->path
);
3829 TRACE(" destroying ITypeLib(%p)\n",This
);
3833 SysFreeString(This
->Name
);
3837 if (This
->DocString
)
3839 SysFreeString(This
->DocString
);
3840 This
->DocString
= NULL
;
3845 SysFreeString(This
->HelpFile
);
3846 This
->HelpFile
= NULL
;
3849 if (This
->HelpStringDll
)
3851 SysFreeString(This
->HelpStringDll
);
3852 This
->HelpStringDll
= NULL
;
3855 for (pCustData
= This
->pCustData
; pCustData
; pCustData
= pCustDataNext
)
3857 VariantClear(&pCustData
->data
);
3859 pCustDataNext
= pCustData
->next
;
3860 TLB_Free(pCustData
);
3863 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
3864 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
3865 TLB_Free(This
->pTypeDesc
[i
].u
.lpadesc
);
3867 TLB_Free(This
->pTypeDesc
);
3869 for (pImpLib
= This
->pImpLibs
; pImpLib
; pImpLib
= pImpLibNext
)
3871 if (pImpLib
->pImpTypeLib
)
3872 ITypeLib_Release((ITypeLib
*)pImpLib
->pImpTypeLib
);
3873 TLB_Free(pImpLib
->name
);
3875 pImpLibNext
= pImpLib
->next
;
3879 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
3881 list_remove(&ref_type
->entry
);
3885 if (This
->pTypeInfo
) /* can be NULL */
3886 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3887 HeapFree(GetProcessHeap(),0,This
);
3894 /* ITypeLib::GetTypeInfoCount
3896 * Returns the number of type descriptions in the type library
3898 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3900 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3901 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3902 return This
->TypeInfoCount
;
3905 /* ITypeLib::GetTypeInfo
3907 * retrieves the specified type description in the library.
3909 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3912 ITypeInfo
**ppTInfo
)
3916 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3917 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3919 TRACE("(%p)->(index=%d)\n", This
, index
);
3921 if (!ppTInfo
) return E_INVALIDARG
;
3923 /* search element n in list */
3924 for(i
=0; i
< index
; i
++)
3926 pTypeInfo
= pTypeInfo
->next
;
3929 TRACE("-- element not found\n");
3930 return TYPE_E_ELEMENTNOTFOUND
;
3934 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3936 ITypeInfo_AddRef(*ppTInfo
);
3937 TRACE("-- found (%p)\n",*ppTInfo
);
3942 /* ITypeLibs::GetTypeInfoType
3944 * Retrieves the type of a type description.
3946 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3951 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3953 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3955 if (ITypeLib2_fnGetTypeInfoCount(iface
) < index
+ 1)
3956 return TYPE_E_ELEMENTNOTFOUND
;
3958 TRACE("(%p) index %d\n", This
, index
);
3960 if(!pTKind
) return E_INVALIDARG
;
3962 /* search element n in list */
3963 for(i
=0; i
< index
; i
++)
3967 TRACE("-- element not found\n");
3968 return TYPE_E_ELEMENTNOTFOUND
;
3970 pTInfo
= pTInfo
->next
;
3973 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3974 TRACE("-- found Type (%d)\n", *pTKind
);
3978 /* ITypeLib::GetTypeInfoOfGuid
3980 * Retrieves the type description that corresponds to the specified GUID.
3983 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3986 ITypeInfo
**ppTInfo
)
3988 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3989 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3991 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3995 WARN("-- element not found\n");
3996 return TYPE_E_ELEMENTNOTFOUND
;
3999 /* search linked list for guid */
4000 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
4002 pTypeInfo
= pTypeInfo
->next
;
4006 /* end of list reached */
4007 WARN("-- element not found\n");
4008 return TYPE_E_ELEMENTNOTFOUND
;
4012 TRACE("-- found (%p, %s)\n",
4014 debugstr_w(pTypeInfo
->Name
));
4016 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
4017 ITypeInfo_AddRef(*ppTInfo
);
4021 /* ITypeLib::GetLibAttr
4023 * Retrieves the structure that contains the library's attributes.
4026 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4028 LPTLIBATTR
*ppTLibAttr
)
4030 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4031 TRACE("(%p)\n",This
);
4032 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
4033 **ppTLibAttr
= This
->LibAttr
;
4037 /* ITypeLib::GetTypeComp
4039 * Enables a client compiler to bind to a library's types, variables,
4040 * constants, and global functions.
4043 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4045 ITypeComp
**ppTComp
)
4047 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4049 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4050 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4051 ITypeComp_AddRef(*ppTComp
);
4056 /* ITypeLib::GetDocumentation
4058 * Retrieves the library's documentation string, the complete Help file name
4059 * and path, and the context identifier for the library Help topic in the Help
4062 * On a successful return all non-null BSTR pointers will have been set,
4065 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4069 BSTR
*pBstrDocString
,
4070 DWORD
*pdwHelpContext
,
4071 BSTR
*pBstrHelpFile
)
4073 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4075 HRESULT result
= E_INVALIDARG
;
4080 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4082 pBstrName
, pBstrDocString
,
4083 pdwHelpContext
, pBstrHelpFile
);
4087 /* documentation for the typelib */
4092 if(!(*pBstrName
= SysAllocString(This
->Name
)))
4100 if (This
->DocString
)
4102 if(!(*pBstrDocString
= SysAllocString(This
->DocString
)))
4105 else if (This
->Name
)
4107 if(!(*pBstrDocString
= SysAllocString(This
->Name
)))
4111 *pBstrDocString
= NULL
;
4115 *pdwHelpContext
= This
->dwHelpContext
;
4121 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
)))
4125 *pBstrHelpFile
= NULL
;
4132 /* for a typeinfo */
4133 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4135 if(SUCCEEDED(result
))
4137 result
= ITypeInfo_GetDocumentation(pTInfo
,
4141 pdwHelpContext
, pBstrHelpFile
);
4143 ITypeInfo_Release(pTInfo
);
4148 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
4150 if (pBstrName
) SysFreeString (*pBstrName
);
4152 return STG_E_INSUFFICIENTMEMORY
;
4157 * Indicates whether a passed-in string contains the name of a type or member
4158 * described in the library.
4161 static HRESULT WINAPI
ITypeLib2_fnIsName(
4167 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4168 ITypeInfoImpl
*pTInfo
;
4169 TLBFuncDesc
*pFInfo
;
4172 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
4174 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
4178 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
4179 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4180 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
4181 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4182 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
4183 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
4184 goto ITypeLib2_fnIsName_exit
;
4186 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
4187 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4192 ITypeLib2_fnIsName_exit
:
4193 TRACE("(%p)slow! search for %s: %s found!\n", This
,
4194 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
4199 /* ITypeLib::FindName
4201 * Finds occurrences of a type description in a type library. This may be used
4202 * to quickly verify that a name exists in a type library.
4205 static HRESULT WINAPI
ITypeLib2_fnFindName(
4209 ITypeInfo
**ppTInfo
,
4213 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4214 ITypeInfoImpl
*pTInfo
;
4215 TLBFuncDesc
*pFInfo
;
4218 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
4220 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
4221 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4222 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
4223 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4224 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++) {
4225 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
4226 goto ITypeLib2_fnFindName_exit
;
4229 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
4230 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4232 ITypeLib2_fnFindName_exit
:
4233 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
4234 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
4237 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4238 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
4245 /* ITypeLib::ReleaseTLibAttr
4247 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4250 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
4252 TLIBATTR
*pTLibAttr
)
4254 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4255 TRACE("freeing (%p)\n",This
);
4256 HeapFree(GetProcessHeap(),0,pTLibAttr
);
4260 /* ITypeLib2::GetCustData
4262 * gets the custom data
4264 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
4269 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4270 TLBCustData
*pCData
;
4272 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
4274 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4277 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4281 VariantInit( pVarVal
);
4282 VariantCopy( pVarVal
, &pCData
->data
);
4285 return E_INVALIDARG
; /* FIXME: correct? */
4288 /* ITypeLib2::GetLibStatistics
4290 * Returns statistics about a type library that are required for efficient
4291 * sizing of hash tables.
4294 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
4296 ULONG
*pcUniqueNames
,
4297 ULONG
*pcchUniqueNames
)
4299 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4301 FIXME("(%p): stub!\n", This
);
4303 if(pcUniqueNames
) *pcUniqueNames
=1;
4304 if(pcchUniqueNames
) *pcchUniqueNames
=1;
4308 /* ITypeLib2::GetDocumentation2
4310 * Retrieves the library's documentation string, the complete Help file name
4311 * and path, the localization context to use, and the context ID for the
4312 * library Help topic in the Help file.
4315 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
4319 BSTR
*pbstrHelpString
,
4320 DWORD
*pdwHelpStringContext
,
4321 BSTR
*pbstrHelpStringDll
)
4323 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4327 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
4329 /* the help string should be obtained from the helpstringdll,
4330 * using the _DLLGetDocumentation function, based on the supplied
4331 * lcid. Nice to do sometime...
4335 /* documentation for the typelib */
4337 *pbstrHelpString
=SysAllocString(This
->DocString
);
4338 if(pdwHelpStringContext
)
4339 *pdwHelpStringContext
=This
->dwHelpContext
;
4340 if(pbstrHelpStringDll
)
4341 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
4347 /* for a typeinfo */
4348 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
4350 if(SUCCEEDED(result
))
4352 ITypeInfo2
* pTInfo2
;
4353 result
= ITypeInfo_QueryInterface(pTInfo
,
4355 (LPVOID
*) &pTInfo2
);
4357 if(SUCCEEDED(result
))
4359 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
4363 pdwHelpStringContext
,
4364 pbstrHelpStringDll
);
4366 ITypeInfo2_Release(pTInfo2
);
4369 ITypeInfo_Release(pTInfo
);
4375 /* ITypeLib2::GetAllCustData
4377 * Gets all custom data items for the library.
4380 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
4382 CUSTDATA
*pCustData
)
4384 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4385 TLBCustData
*pCData
;
4387 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
4388 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
4389 if(pCustData
->prgCustData
){
4390 pCustData
->cCustData
=This
->ctCustData
;
4391 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
4392 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4393 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
4396 ERR(" OUT OF MEMORY!\n");
4397 return E_OUTOFMEMORY
;
4402 static const ITypeLib2Vtbl tlbvt
= {
4403 ITypeLib2_fnQueryInterface
,
4405 ITypeLib2_fnRelease
,
4406 ITypeLib2_fnGetTypeInfoCount
,
4407 ITypeLib2_fnGetTypeInfo
,
4408 ITypeLib2_fnGetTypeInfoType
,
4409 ITypeLib2_fnGetTypeInfoOfGuid
,
4410 ITypeLib2_fnGetLibAttr
,
4411 ITypeLib2_fnGetTypeComp
,
4412 ITypeLib2_fnGetDocumentation
,
4414 ITypeLib2_fnFindName
,
4415 ITypeLib2_fnReleaseTLibAttr
,
4417 ITypeLib2_fnGetCustData
,
4418 ITypeLib2_fnGetLibStatistics
,
4419 ITypeLib2_fnGetDocumentation2
,
4420 ITypeLib2_fnGetAllCustData
4424 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4426 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4428 return ITypeLib2_QueryInterface((ITypeLib
*)This
, riid
, ppv
);
4431 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4433 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4435 return ITypeLib2_AddRef((ITypeLib2
*)This
);
4438 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4440 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4442 return ITypeLib2_Release((ITypeLib2
*)This
);
4445 static HRESULT WINAPI
ITypeLibComp_fnBind(
4450 ITypeInfo
** ppTInfo
,
4451 DESCKIND
* pDescKind
,
4454 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4455 ITypeInfoImpl
*pTypeInfo
;
4457 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4459 *pDescKind
= DESCKIND_NONE
;
4460 pBindPtr
->lptcomp
= NULL
;
4463 for (pTypeInfo
= This
->pTypeInfo
; pTypeInfo
; pTypeInfo
= pTypeInfo
->next
)
4465 TRACE("testing %s\n", debugstr_w(pTypeInfo
->Name
));
4467 /* FIXME: check wFlags here? */
4468 /* FIXME: we should use a hash table to look this info up using lHash
4469 * instead of an O(n) search */
4470 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
) ||
4471 (pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
))
4473 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
, szName
))
4475 *pDescKind
= DESCKIND_TYPECOMP
;
4476 pBindPtr
->lptcomp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4477 ITypeComp_AddRef(pBindPtr
->lptcomp
);
4478 TRACE("module or enum: %s\n", debugstr_w(szName
));
4483 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
) ||
4484 (pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
))
4486 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4489 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4490 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
4492 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
4497 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_COCLASS
) &&
4498 (pTypeInfo
->TypeAttr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
4500 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4502 ITypeInfo
*subtypeinfo
;
4504 DESCKIND subdesckind
;
4506 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
4507 &subtypeinfo
, &subdesckind
, &subbindptr
);
4508 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
4510 TYPEDESC tdesc_appobject
=
4513 (TYPEDESC
*)pTypeInfo
->hreftype
4517 const VARDESC vardesc_appobject
=
4520 NULL
, /* lpstrSchema */
4535 VAR_STATIC
/* varkind */
4538 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
4540 /* cleanup things filled in by Bind call so we can put our
4541 * application object data in there instead */
4542 switch (subdesckind
)
4544 case DESCKIND_FUNCDESC
:
4545 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
4547 case DESCKIND_VARDESC
:
4548 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
4553 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
4555 if (pTypeInfo
->hreftype
== -1)
4556 FIXME("no hreftype for interface %p\n", pTypeInfo
);
4558 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
4562 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
4563 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
4564 ITypeInfo_AddRef(*ppTInfo
);
4570 TRACE("name not found %s\n", debugstr_w(szName
));
4574 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4578 ITypeInfo
** ppTInfo
,
4579 ITypeComp
** ppTComp
)
4581 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4585 static const ITypeCompVtbl tlbtcvt
=
4588 ITypeLibComp_fnQueryInterface
,
4589 ITypeLibComp_fnAddRef
,
4590 ITypeLibComp_fnRelease
,
4592 ITypeLibComp_fnBind
,
4593 ITypeLibComp_fnBindType
4596 /*================== ITypeInfo(2) Methods ===================================*/
4597 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
4599 ITypeInfoImpl
* pTypeInfoImpl
;
4601 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4604 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4605 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4606 pTypeInfoImpl
->ref
=1;
4607 pTypeInfoImpl
->hreftype
= -1;
4608 pTypeInfoImpl
->TypeAttr
.memidConstructor
= MEMBERID_NIL
;
4609 pTypeInfoImpl
->TypeAttr
.memidDestructor
= MEMBERID_NIL
;
4611 TRACE("(%p)\n", pTypeInfoImpl
);
4612 return (ITypeInfo2
*) pTypeInfoImpl
;
4615 /* ITypeInfo::QueryInterface
4617 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4622 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4624 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4627 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4628 IsEqualIID(riid
,&IID_ITypeInfo
)||
4629 IsEqualIID(riid
,&IID_ITypeInfo2
))
4633 ITypeInfo_AddRef(iface
);
4634 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4637 TRACE("-- Interface: E_NOINTERFACE\n");
4638 return E_NOINTERFACE
;
4641 /* ITypeInfo::AddRef
4643 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4645 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4646 ULONG ref
= InterlockedIncrement(&This
->ref
);
4648 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4650 TRACE("(%p)->ref is %u\n",This
, ref
);
4654 /* ITypeInfo::Release
4656 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
4658 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4659 ULONG ref
= InterlockedDecrement(&This
->ref
);
4661 TRACE("(%p)->(%u)\n",This
, ref
);
4664 /* We don't release ITypeLib when ref=0 because
4665 it means that function is called by ITypeLib2_Release */
4666 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
4668 TLBFuncDesc
*pFInfo
, *pFInfoNext
;
4669 TLBVarDesc
*pVInfo
, *pVInfoNext
;
4670 TLBImplType
*pImpl
, *pImplNext
;
4672 TRACE("destroying ITypeInfo(%p)\n",This
);
4674 if (This
->no_free_data
)
4679 SysFreeString(This
->Name
);
4683 if (This
->DocString
)
4685 SysFreeString(This
->DocString
);
4686 This
->DocString
= 0;
4691 SysFreeString(This
->DllName
);
4695 for (pFInfo
= This
->funclist
; pFInfo
; pFInfo
= pFInfoNext
)
4698 for(i
= 0;i
< pFInfo
->funcdesc
.cParams
; i
++)
4700 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[i
];
4701 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4703 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
4704 TLB_Free(elemdesc
->u
.paramdesc
.pparamdescex
);
4706 SysFreeString(pFInfo
->pParamDesc
[i
].Name
);
4708 TLB_Free(pFInfo
->funcdesc
.lprgelemdescParam
);
4709 TLB_Free(pFInfo
->pParamDesc
);
4710 TLB_FreeCustData(pFInfo
->pCustData
);
4711 if (HIWORD(pFInfo
->Entry
) != 0 && pFInfo
->Entry
!= (BSTR
)-1)
4712 SysFreeString(pFInfo
->Entry
);
4713 SysFreeString(pFInfo
->HelpString
);
4714 SysFreeString(pFInfo
->Name
);
4716 pFInfoNext
= pFInfo
->next
;
4719 for (pVInfo
= This
->varlist
; pVInfo
; pVInfo
= pVInfoNext
)
4721 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
4723 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
4724 TLB_Free(pVInfo
->vardesc
.u
.lpvarValue
);
4726 TLB_FreeCustData(pVInfo
->pCustData
);
4727 SysFreeString(pVInfo
->Name
);
4728 pVInfoNext
= pVInfo
->next
;
4731 for(pImpl
= This
->impltypelist
; pImpl
; pImpl
= pImplNext
)
4733 TLB_FreeCustData(pImpl
->pCustData
);
4734 pImplNext
= pImpl
->next
;
4737 TLB_FreeCustData(This
->pCustData
);
4742 ITypeInfo_Release((ITypeInfo
*)This
->next
);
4745 HeapFree(GetProcessHeap(),0,This
);
4751 /* ITypeInfo::GetTypeAttr
4753 * Retrieves a TYPEATTR structure that contains the attributes of the type
4757 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
4758 LPTYPEATTR
*ppTypeAttr
)
4760 const ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4763 TRACE("(%p)\n",This
);
4765 size
= sizeof(**ppTypeAttr
);
4766 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
4767 size
+= TLB_SizeTypeDesc(&This
->TypeAttr
.tdescAlias
, FALSE
);
4769 *ppTypeAttr
= HeapAlloc(GetProcessHeap(), 0, size
);
4771 return E_OUTOFMEMORY
;
4773 **ppTypeAttr
= This
->TypeAttr
;
4775 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
4776 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
4777 &This
->TypeAttr
.tdescAlias
, (void *)(*ppTypeAttr
+ 1));
4779 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
4780 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ 4; /* This should include all the inherited
4782 (*ppTypeAttr
)->cbSizeVft
= 28; /* This is always the size of IDispatch's vtbl */
4783 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
4788 /* ITypeInfo::GetTypeComp
4790 * Retrieves the ITypeComp interface for the type description, which enables a
4791 * client compiler to bind to the type description's members.
4794 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
4795 ITypeComp
* *ppTComp
)
4797 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4799 TRACE("(%p)->(%p)\n", This
, ppTComp
);
4801 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4802 ITypeComp_AddRef(*ppTComp
);
4806 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
4808 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
4809 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4810 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
4814 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
4817 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
4818 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4820 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
4821 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
4822 *buffer
+= sizeof(PARAMDESCEX
);
4823 *pparamdescex_dest
= *pparamdescex_src
;
4824 VariantInit(&pparamdescex_dest
->varDefaultValue
);
4825 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
4826 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
4829 dest
->u
.paramdesc
.pparamdescex
= NULL
;
4833 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
4835 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4836 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
4839 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
4843 SIZE_T size
= sizeof(*src
);
4847 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
4848 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
4849 for (i
= 0; i
< src
->cParams
; i
++)
4851 size
+= sizeof(ELEMDESC
);
4852 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
4855 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
4856 if (!dest
) return E_OUTOFMEMORY
;
4859 if (dispinterface
) /* overwrite funckind */
4860 dest
->funckind
= FUNC_DISPATCH
;
4861 buffer
= (char *)(dest
+ 1);
4863 dest
->lprgscode
= (SCODE
*)buffer
;
4864 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
4865 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
4867 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
4870 SysFreeString((BSTR
)dest
);
4874 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
4875 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
4876 for (i
= 0; i
< src
->cParams
; i
++)
4878 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
4884 /* undo the above actions */
4885 for (i
= i
- 1; i
>= 0; i
--)
4886 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
4887 TLB_FreeElemDesc(&dest
->elemdescFunc
);
4888 SysFreeString((BSTR
)dest
);
4892 /* special treatment for dispinterfaces: this makes functions appear
4893 * to return their [retval] value when it is really returning an
4895 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
4897 if (dest
->cParams
&&
4898 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
4900 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
4901 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
4903 ERR("elemdesc should have started with VT_PTR instead of:\n");
4905 dump_ELEMDESC(elemdesc
);
4906 return E_UNEXPECTED
;
4909 /* copy last parameter to the return value. we are using a flat
4910 * buffer so there is no danger of leaking memory in
4912 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
4914 /* remove the last parameter */
4918 /* otherwise this function is made to appear to have no return
4920 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
4928 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
4930 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4931 const TLBFuncDesc
*pFDesc
;
4934 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
4939 *ppFuncDesc
= &pFDesc
->funcdesc
;
4943 return TYPE_E_ELEMENTNOTFOUND
;
4946 /* internal function to make the inherited interfaces' methods appear
4947 * part of the interface */
4948 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
4949 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
4951 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4953 UINT implemented_funcs
= 0;
4958 *hrefoffset
= DISPATCH_HREF_OFFSET
;
4960 if(This
->impltypelist
)
4962 ITypeInfo
*pSubTypeInfo
;
4965 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pSubTypeInfo
);
4969 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
4972 &sub_funcs
, hrefoffset
);
4973 implemented_funcs
+= sub_funcs
;
4974 ITypeInfo_Release(pSubTypeInfo
);
4977 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
4981 *funcs
= implemented_funcs
+ This
->TypeAttr
.cFuncs
;
4985 if (index
< implemented_funcs
)
4986 return E_INVALIDARG
;
4987 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
4991 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
4993 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
4996 switch (pTypeDesc
->vt
)
4998 case VT_USERDEFINED
:
4999 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5003 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5006 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5014 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5017 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5018 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5019 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5022 /* ITypeInfo::GetFuncDesc
5024 * Retrieves the FUNCDESC structure that contains information about a
5025 * specified function.
5028 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5029 LPFUNCDESC
*ppFuncDesc
)
5031 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5032 const FUNCDESC
*internal_funcdesc
;
5034 UINT hrefoffset
= 0;
5036 TRACE("(%p) index %d\n", This
, index
);
5038 if (This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5039 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5040 &internal_funcdesc
, NULL
,
5043 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5044 &internal_funcdesc
);
5047 WARN("description for function %d not found\n", index
);
5051 hr
= TLB_AllocAndInitFuncDesc(
5054 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
5056 if ((This
->TypeAttr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
5057 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5059 TRACE("-- 0x%08x\n", hr
);
5063 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5067 SIZE_T size
= sizeof(*src
);
5070 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
5071 if (src
->varkind
== VAR_CONST
)
5072 size
+= sizeof(VARIANT
);
5073 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
5075 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
5076 if (!dest
) return E_OUTOFMEMORY
;
5079 buffer
= (char *)(dest
+ 1);
5080 if (src
->lpstrSchema
)
5083 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
5084 len
= strlenW(src
->lpstrSchema
);
5085 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
5086 buffer
+= (len
+ 1) * sizeof(WCHAR
);
5089 if (src
->varkind
== VAR_CONST
)
5093 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
5094 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
5095 buffer
+= sizeof(VARIANT
);
5096 VariantInit(dest
->u
.lpvarValue
);
5097 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
5100 SysFreeString((BSTR
)dest_ptr
);
5104 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
5107 if (src
->varkind
== VAR_CONST
)
5108 VariantClear(dest
->u
.lpvarValue
);
5109 SysFreeString((BSTR
)dest
);
5116 /* ITypeInfo::GetVarDesc
5118 * Retrieves a VARDESC structure that describes the specified variable.
5121 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
5122 LPVARDESC
*ppVarDesc
)
5124 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5126 const TLBVarDesc
*pVDesc
;
5128 TRACE("(%p) index %d\n", This
, index
);
5130 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
5134 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
5136 return E_INVALIDARG
;
5139 /* ITypeInfo_GetNames
5141 * Retrieves the variable with the specified member ID (or the name of the
5142 * property or method and its parameters) that correspond to the specified
5145 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
5146 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
5148 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5149 const TLBFuncDesc
*pFDesc
;
5150 const TLBVarDesc
*pVDesc
;
5152 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
5153 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
5156 /* function found, now return function and parameter names */
5157 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
5160 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
5162 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
5168 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
5171 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
5176 if(This
->impltypelist
&&
5177 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
5178 /* recursive search */
5181 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
5183 if(SUCCEEDED(result
))
5185 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
5186 ITypeInfo_Release(pTInfo
);
5189 WARN("Could not search inherited interface!\n");
5193 WARN("no names found\n");
5196 return TYPE_E_ELEMENTNOTFOUND
;
5203 /* ITypeInfo::GetRefTypeOfImplType
5205 * If a type description describes a COM class, it retrieves the type
5206 * description of the implemented interface types. For an interface,
5207 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5211 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
5216 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5219 const TLBImplType
*pImpl
= This
->impltypelist
;
5221 TRACE("(%p) index %d\n", This
, index
);
5222 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
5226 /* only valid on dual interfaces;
5227 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5229 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
5231 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
5232 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
5238 hr
= TYPE_E_ELEMENTNOTFOUND
;
5241 else if(index
== 0 && This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5243 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5244 *pRefType
= This
->pTypeLib
->dispatch_href
;
5248 /* get element n from linked list */
5249 for(i
=0; pImpl
&& i
<index
; i
++)
5251 pImpl
= pImpl
->next
;
5255 *pRefType
= pImpl
->hRef
;
5257 hr
= TYPE_E_ELEMENTNOTFOUND
;
5263 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
5265 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
5271 /* ITypeInfo::GetImplTypeFlags
5273 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5274 * or base interface in a type description.
5276 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
5277 UINT index
, INT
*pImplTypeFlags
)
5279 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5283 TRACE("(%p) index %d\n", This
, index
);
5284 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
5285 i
++, pImpl
=pImpl
->next
)
5287 if(i
==index
&& pImpl
){
5288 *pImplTypeFlags
=pImpl
->implflags
;
5292 return TYPE_E_ELEMENTNOTFOUND
;
5296 * Maps between member names and member IDs, and parameter names and
5299 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
5300 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
5302 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5303 const TLBFuncDesc
*pFDesc
;
5304 const TLBVarDesc
*pVDesc
;
5308 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
5311 /* init out parameters in case of failure */
5312 for (i
= 0; i
< cNames
; i
++)
5313 pMemId
[i
] = MEMBERID_NIL
;
5315 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
5317 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
5318 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
5319 for(i
=1; i
< cNames
; i
++){
5320 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
5321 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
5323 if( j
<pFDesc
->funcdesc
.cParams
)
5326 ret
=DISP_E_UNKNOWNNAME
;
5328 TRACE("-- 0x%08x\n", ret
);
5332 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
5333 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
5334 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
5338 /* not found, see if it can be found in an inherited interface */
5339 if(This
->impltypelist
) {
5340 /* recursive search */
5342 ret
=ITypeInfo_GetRefTypeInfo(iface
,
5343 This
->impltypelist
->hRef
, &pTInfo
);
5345 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
5346 ITypeInfo_Release(pTInfo
);
5349 WARN("Could not search inherited interface!\n");
5351 WARN("no names found\n");
5352 return DISP_E_UNKNOWNNAME
;
5355 /* ITypeInfo::Invoke
5357 * Invokes a method, or accesses a property of an object, that implements the
5358 * interface described by the type description.
5361 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
5364 if (TRACE_ON(ole
)) {
5366 TRACE("Calling %p(",func
);
5367 for (i
=0;i
<nrargs
;i
++) TRACE("%08x,",args
[i
]);
5379 res
= func(args
[0]);
5382 res
= func(args
[0],args
[1]);
5385 res
= func(args
[0],args
[1],args
[2]);
5388 res
= func(args
[0],args
[1],args
[2],args
[3]);
5391 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
5394 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
5397 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
5400 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
5403 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
5406 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9]);
5409 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10]);
5412 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11]);
5415 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12]);
5418 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13]);
5421 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14]);
5424 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15]);
5427 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16]);
5430 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17]);
5433 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18]);
5436 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19]);
5439 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19],args
[20]);
5442 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19],args
[20],args
[21]);
5445 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19],args
[20],args
[21],args
[22]);
5448 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19],args
[20],args
[21],args
[22],args
[23]);
5451 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19],args
[20],args
[21],args
[22],args
[23],args
[24]);
5454 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19],args
[20],args
[21],args
[22],args
[23],args
[24],args
[25]);
5457 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19],args
[20],args
[21],args
[22],args
[23],args
[24],args
[25],args
[26]);
5460 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19],args
[20],args
[21],args
[22],args
[23],args
[24],args
[25],args
[26],args
[27]);
5463 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19],args
[20],args
[21],args
[22],args
[23],args
[24],args
[25],args
[26],args
[27],args
[28]);
5466 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19],args
[20],args
[21],args
[22],args
[23],args
[24],args
[25],args
[26],args
[27],args
[28],args
[29]);
5469 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
5475 FIXME("unsupported calling convention %d\n",callconv
);
5479 TRACE("returns %08x\n",res
);
5483 extern int _argsize(DWORD vt
);
5485 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5488 ITypeInfo
*tinfo2
= NULL
;
5489 TYPEATTR
*tattr
= NULL
;
5491 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
5494 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5496 tdesc
->u
.hreftype
, hr
);
5499 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
5502 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
5503 ITypeInfo_Release(tinfo2
);
5507 switch (tattr
->typekind
)
5514 tdesc
= &tattr
->tdescAlias
;
5515 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
5518 case TKIND_INTERFACE
:
5519 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
5525 case TKIND_DISPATCH
:
5534 FIXME("TKIND_RECORD unhandled.\n");
5539 FIXME("TKIND_UNION unhandled.\n");
5544 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
5548 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
5549 ITypeInfo_Release(tinfo2
);
5553 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5557 /* enforce only one level of pointer indirection */
5558 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
5560 tdesc
= tdesc
->u
.lptdesc
;
5562 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5563 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5564 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5565 if ((tdesc
->vt
== VT_USERDEFINED
) ||
5566 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
5568 VARTYPE vt_userdefined
= 0;
5569 const TYPEDESC
*tdesc_userdefined
= tdesc
;
5570 if (tdesc
->vt
== VT_PTR
)
5572 vt_userdefined
= VT_BYREF
;
5573 tdesc_userdefined
= tdesc
->u
.lptdesc
;
5575 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
5577 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
5578 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
5580 *vt
|= vt_userdefined
;
5592 case VT_USERDEFINED
:
5593 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
5600 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
5601 hr
= DISP_E_BADVARTYPE
;
5605 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
5614 /***********************************************************************
5615 * DispCallFunc (OLEAUT32.@)
5617 * Invokes a function of the specified calling convention, passing the
5618 * specified arguments and returns the result.
5621 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5622 * oVft [I] The offset in the vtable. See notes.
5623 * cc [I] Calling convention of the function to call.
5624 * vtReturn [I] The return type of the function.
5625 * cActuals [I] Number of parameters.
5626 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5627 * prgpvarg [I] The arguments to pass.
5628 * pvargResult [O] The return value of the function. Can be NULL.
5632 * Failure: HRESULT code.
5635 * The HRESULT return value of this function is not affected by the return
5636 * value of the user supplied function, which is returned in pvargResult.
5638 * If pvInstance is NULL then a non-object function is to be called and oVft
5639 * is the address of the function to call.
5641 * The cc parameter can be one of the following values:
5654 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
5655 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
5657 int i
, argsize
, argspos
;
5661 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5662 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
5663 pvargResult
, V_VT(pvargResult
));
5667 argsize
++; /* for This pointer */
5669 for (i
=0;i
<cActuals
;i
++)
5671 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
5672 dump_Variant(prgpvarg
[i
]);
5673 argsize
+= _argsize(prgvt
[i
]);
5675 args
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
5680 args
[0] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
5684 for (i
=0;i
<cActuals
;i
++)
5686 VARIANT
*arg
= prgpvarg
[i
];
5687 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
5688 if (prgvt
[i
] == VT_VARIANT
)
5689 memcpy(&args
[argspos
], arg
, _argsize(prgvt
[i
]) * sizeof(DWORD
));
5691 memcpy(&args
[argspos
], &V_NONE(arg
), _argsize(prgvt
[i
]) * sizeof(DWORD
));
5692 argspos
+= _argsize(prgvt
[i
]);
5697 FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
5698 hres
= _invoke(vtable
[oVft
/sizeof(void *)], cc
, argsize
, args
);
5701 /* if we aren't invoking an object then the function pointer is stored
5703 hres
= _invoke((FARPROC
)oVft
, cc
, argsize
, args
);
5705 if (pvargResult
&& (vtReturn
!= VT_EMPTY
))
5707 TRACE("Method returned 0x%08x\n",hres
);
5708 V_VT(pvargResult
) = vtReturn
;
5709 V_UI4(pvargResult
) = hres
;
5712 HeapFree(GetProcessHeap(),0,args
);
5716 #define INVBUF_ELEMENT_SIZE \
5717 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5718 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5719 ((VARIANTARG *)(buffer))
5720 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5721 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5722 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5723 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5724 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5725 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5727 static HRESULT WINAPI
ITypeInfo_fnInvoke(
5732 DISPPARAMS
*pDispParams
,
5733 VARIANT
*pVarResult
,
5734 EXCEPINFO
*pExcepInfo
,
5737 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5739 unsigned int var_index
;
5742 const TLBFuncDesc
*pFuncInfo
;
5744 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5745 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
5750 ERR("NULL pDispParams not allowed\n");
5751 return E_INVALIDARG
;
5754 dump_DispParms(pDispParams
);
5756 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
5758 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5759 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
5760 return E_INVALIDARG
;
5763 /* we do this instead of using GetFuncDesc since it will return a fake
5764 * FUNCDESC for dispinterfaces and we want the real function description */
5765 for (pFuncInfo
= This
->funclist
; pFuncInfo
; pFuncInfo
=pFuncInfo
->next
)
5766 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
5767 (wFlags
& pFuncInfo
->funcdesc
.invkind
))
5771 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
5775 TRACE("invoking:\n");
5776 dump_TLBFuncDescOne(pFuncInfo
);
5779 switch (func_desc
->funckind
) {
5780 case FUNC_PUREVIRTUAL
:
5781 case FUNC_VIRTUAL
: {
5782 void *buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
5784 VARIANT retval
; /* pointer for storing byref retvals in */
5785 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
5786 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
5787 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
5788 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
5789 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
5793 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
5795 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
5797 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5798 hres
= DISP_E_PARAMNOTFOUND
;
5801 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5803 rgdispidNamedArgs
++;
5806 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
5808 ERR("functions with the vararg attribute do not support named arguments\n");
5809 hres
= DISP_E_NONAMEDARGS
;
5813 for (i
= 0; i
< func_desc
->cParams
; i
++)
5815 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
5816 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
5821 TRACE("changing args\n");
5822 for (i
= 0; i
< func_desc
->cParams
; i
++)
5824 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
5825 VARIANTARG
*src_arg
;
5831 for (j
= 0; j
< cNamedArgs
; j
++)
5832 if (rgdispidNamedArgs
[j
] == i
)
5834 src_arg
= &pDispParams
->rgvarg
[j
];
5839 src_arg
= i
< pDispParams
->cArgs
? &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
] : NULL
;
5841 if (wParamFlags
& PARAMFLAG_FRETVAL
)
5843 /* under most conditions the caller is not allowed to
5844 * pass in a dispparam arg in the index of what would be
5845 * the retval parameter. however, there is an exception
5846 * where the extra parameter is used in an extra
5847 * IDispatch::Invoke below */
5848 if ((i
< pDispParams
->cArgs
) &&
5849 ((func_desc
->cParams
!= 1) || !pVarResult
||
5850 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
5852 hres
= DISP_E_BADPARAMCOUNT
;
5856 /* note: this check is placed so that if the caller passes
5857 * in a VARIANTARG for the retval we just ignore it, like
5859 if (i
== func_desc
->cParams
- 1)
5862 arg
= prgpvarg
[i
] = &rgvarg
[i
];
5863 memset(arg
, 0, sizeof(*arg
));
5864 V_VT(arg
) = rgvt
[i
];
5865 memset(&retval
, 0, sizeof(retval
));
5866 V_BYREF(arg
) = &retval
;
5870 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
5871 hres
= E_UNEXPECTED
;
5877 dump_Variant(src_arg
);
5879 if (rgvt
[i
] == VT_VARIANT
)
5880 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
5881 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
5883 if (rgvt
[i
] == V_VT(src_arg
))
5884 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
5887 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
5888 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
5889 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
5891 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5893 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
5896 SAFEARRAYBOUND bound
;
5900 bound
.cElements
= pDispParams
->cArgs
-i
;
5901 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
5903 ERR("SafeArrayCreate failed\n");
5906 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
5909 ERR("SafeArrayAccessData failed with %x\n", hres
);
5912 for (j
= 0; j
< bound
.cElements
; j
++)
5913 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
5914 hres
= SafeArrayUnaccessData(a
);
5917 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
5920 V_ARRAY(&rgvarg
[i
]) = a
;
5921 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5923 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
5925 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
5926 V_VT(&missing_arg
[i
]) = V_VT(src_arg
);
5927 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
5928 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
5929 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5931 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
5933 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
5934 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5938 /* FIXME: this doesn't work for VT_BYREF arguments if
5939 * they are not the same type as in the paramdesc */
5940 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
5941 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
5942 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5947 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
5948 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
5949 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
5952 prgpvarg
[i
] = &rgvarg
[i
];
5954 else if (wParamFlags
& PARAMFLAG_FOPT
)
5957 arg
= prgpvarg
[i
] = &rgvarg
[i
];
5958 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5960 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
5966 VARIANTARG
*missing_arg
;
5967 /* if the function wants a pointer to a variant then
5968 * set that up, otherwise just pass the VT_ERROR in
5969 * the argument by value */
5970 if (rgvt
[i
] & VT_BYREF
)
5972 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
5973 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
5974 V_VARIANTREF(arg
) = missing_arg
;
5978 V_VT(missing_arg
) = VT_ERROR
;
5979 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
5984 hres
= DISP_E_BADPARAMCOUNT
;
5988 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
5990 /* VT_VOID is a special case for return types, so it is not
5991 * handled in the general function */
5992 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
5993 V_VT(&varresult
) = VT_EMPTY
;
5996 V_VT(&varresult
) = 0;
5997 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
5998 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6001 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
, func_desc
->callconv
,
6002 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
6003 prgpvarg
, &varresult
);
6005 for (i
= 0; i
< func_desc
->cParams
; i
++)
6007 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6008 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6012 TRACE("[retval] value: ");
6013 dump_Variant(prgpvarg
[i
]);
6018 VariantInit(pVarResult
);
6019 /* deref return value */
6020 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
6023 /* free data stored in varresult. Note that
6024 * VariantClear doesn't do what we want because we are
6025 * working with byref types. */
6026 /* FIXME: clear safearrays, bstrs, records and
6027 * variants here too */
6028 if ((V_VT(prgpvarg
[i
]) == (VT_UNKNOWN
| VT_BYREF
)) ||
6029 (V_VT(prgpvarg
[i
]) == (VT_DISPATCH
| VT_BYREF
)))
6031 if(*V_UNKNOWNREF(prgpvarg
[i
]))
6032 IUnknown_Release(*V_UNKNOWNREF(prgpvarg
[i
]));
6036 else if (i
< pDispParams
->cArgs
)
6038 if (wParamFlags
& PARAMFLAG_FOUT
)
6040 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
];
6042 if ((rgvt
[i
] == VT_BYREF
) && (V_VT(arg
) != VT_BYREF
))
6043 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
6047 ERR("failed to convert param %d to vt %d\n", i
,
6048 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
]));
6052 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
6053 func_desc
->cParamsOpt
< 0 &&
6054 i
== func_desc
->cParams
-1)
6056 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
6059 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
6062 ERR("SafeArrayGetUBound failed with %x\n", hres
);
6065 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6068 ERR("SafeArrayAccessData failed with %x\n", hres
);
6071 for (j
= 0; j
<= ubound
; j
++)
6072 VariantClear(&v
[j
]);
6073 hres
= SafeArrayUnaccessData(a
);
6076 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6080 VariantClear(&rgvarg
[i
]);
6082 else if (wParamFlags
& PARAMFLAG_FOPT
)
6084 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6085 VariantClear(&rgvarg
[i
]);
6089 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
6091 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
6092 hres
= DISP_E_EXCEPTION
;
6095 IErrorInfo
*pErrorInfo
;
6096 pExcepInfo
->scode
= V_ERROR(&varresult
);
6097 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
6099 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
6100 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
6101 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
6102 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
6104 IErrorInfo_Release(pErrorInfo
);
6108 if (V_VT(&varresult
) != VT_ERROR
)
6110 TRACE("varresult value: ");
6111 dump_Variant(&varresult
);
6115 VariantClear(pVarResult
);
6116 *pVarResult
= varresult
;
6119 VariantClear(&varresult
);
6122 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
6123 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
6124 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
6125 (pDispParams
->cArgs
!= 0))
6127 if (V_VT(pVarResult
) == VT_DISPATCH
)
6129 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
6130 /* Note: not VariantClear; we still need the dispatch
6131 * pointer to be valid */
6132 VariantInit(pVarResult
);
6133 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
6134 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
6135 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
6136 IDispatch_Release(pDispatch
);
6140 VariantClear(pVarResult
);
6141 hres
= DISP_E_NOTACOLLECTION
;
6146 HeapFree(GetProcessHeap(), 0, buffer
);
6149 case FUNC_DISPATCH
: {
6152 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
6153 if (SUCCEEDED(hres
)) {
6154 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6155 hres
= IDispatch_Invoke(
6156 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
6157 pVarResult
,pExcepInfo
,pArgErr
6160 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
6161 IDispatch_Release(disp
);
6163 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6167 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
6172 TRACE("-- 0x%08x\n", hres
);
6175 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
6178 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
6179 if(FAILED(hres
)) return hres
;
6181 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6182 dump_VARDESC(var_desc
);
6183 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
6187 /* not found, look for it in inherited interfaces */
6188 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
6189 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
6190 if(This
->impltypelist
) {
6191 /* recursive search */
6193 hres
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pTInfo
);
6194 if(SUCCEEDED(hres
)){
6195 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
6196 ITypeInfo_Release(pTInfo
);
6199 WARN("Could not search inherited interface!\n");
6202 ERR("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
6203 return DISP_E_MEMBERNOTFOUND
;
6206 /* ITypeInfo::GetDocumentation
6208 * Retrieves the documentation string, the complete Help file name and path,
6209 * and the context ID for the Help topic for a specified type description.
6211 * (Can be tested by the Visual Basic Editor in Word for instance.)
6213 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
6214 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
6215 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
6217 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6218 const TLBFuncDesc
*pFDesc
;
6219 const TLBVarDesc
*pVDesc
;
6220 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6221 " HelpContext(%p) HelpFile(%p)\n",
6222 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6223 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
6225 *pBstrName
=SysAllocString(This
->Name
);
6227 *pBstrDocString
=SysAllocString(This
->DocString
);
6229 *pdwHelpContext
=This
->dwHelpContext
;
6231 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
6233 }else {/* for a member */
6234 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6235 if(pFDesc
->funcdesc
.memid
==memid
){
6237 *pBstrName
= SysAllocString(pFDesc
->Name
);
6239 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
6241 *pdwHelpContext
=pFDesc
->helpcontext
;
6244 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
6245 if(pVDesc
->vardesc
.memid
==memid
){
6247 *pBstrName
= SysAllocString(pVDesc
->Name
);
6249 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
6251 *pdwHelpContext
=pVDesc
->HelpContext
;
6256 if(This
->impltypelist
&&
6257 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
6258 /* recursive search */
6261 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
6263 if(SUCCEEDED(result
)) {
6264 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
6265 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6266 ITypeInfo_Release(pTInfo
);
6269 WARN("Could not search inherited interface!\n");
6272 WARN("member %d not found\n", memid
);
6273 return TYPE_E_ELEMENTNOTFOUND
;
6276 /* ITypeInfo::GetDllEntry
6278 * Retrieves a description or specification of an entry point for a function
6281 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
6282 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
6285 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6286 const TLBFuncDesc
*pFDesc
;
6288 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
6290 if (pBstrDllName
) *pBstrDllName
= NULL
;
6291 if (pBstrName
) *pBstrName
= NULL
;
6292 if (pwOrdinal
) *pwOrdinal
= 0;
6294 if (This
->TypeAttr
.typekind
!= TKIND_MODULE
)
6295 return TYPE_E_BADMODULEKIND
;
6297 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6298 if(pFDesc
->funcdesc
.memid
==memid
){
6299 dump_TypeInfo(This
);
6301 dump_TLBFuncDescOne(pFDesc
);
6304 *pBstrDllName
= SysAllocString(This
->DllName
);
6306 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
6308 *pBstrName
= SysAllocString(pFDesc
->Entry
);
6316 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
6319 return TYPE_E_ELEMENTNOTFOUND
;
6322 /* internal function to make the inherited interfaces' methods appear
6323 * part of the interface */
6324 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
6325 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
6327 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6330 TRACE("%p, 0x%x\n", iface
, *hRefType
);
6332 if (This
->impltypelist
&& (*hRefType
& DISPATCH_HREF_MASK
))
6334 ITypeInfo
*pSubTypeInfo
;
6336 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pSubTypeInfo
);
6340 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
6342 ITypeInfo_Release(pSubTypeInfo
);
6346 *hRefType
-= DISPATCH_HREF_OFFSET
;
6348 if (!(*hRefType
& DISPATCH_HREF_MASK
))
6349 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
6354 /* ITypeInfo::GetRefTypeInfo
6356 * If a type description references other type descriptions, it retrieves
6357 * the referenced type descriptions.
6359 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
6362 ITypeInfo
**ppTInfo
)
6364 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6365 HRESULT result
= E_FAIL
;
6367 if ((This
->hreftype
!= -1) && (This
->hreftype
== hRefType
))
6369 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6370 ITypeInfo_AddRef(*ppTInfo
);
6373 else if (hRefType
== -1 &&
6374 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
6375 (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
6377 /* when we meet a DUAL dispinterface, we must create the interface
6380 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
6383 /* the interface version contains the same information as the dispinterface
6384 * copy the contents of the structs.
6386 *pTypeInfoImpl
= *This
;
6387 pTypeInfoImpl
->ref
= 0;
6389 /* change the type to interface */
6390 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
6392 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
6394 /* we use data structures from This, so we need to keep a reference
6395 * to it to stop it being destroyed and signal to the new instance to
6396 * not free its data structures when it is destroyed */
6397 pTypeInfoImpl
->no_free_data
= TRUE
;
6398 pTypeInfoImpl
->next
= This
;
6399 ITypeInfo_AddRef((ITypeInfo
*) This
);
6401 ITypeInfo_AddRef(*ppTInfo
);
6405 } else if ((hRefType
!= -1) && (hRefType
& DISPATCH_HREF_MASK
) &&
6406 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
6407 (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
6409 HREFTYPE href_dispatch
= hRefType
;
6410 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
6412 TLBRefType
*ref_type
;
6413 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
6415 if(ref_type
->reference
== hRefType
)
6418 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
6420 FIXME("Can't find pRefType for ref %x\n", hRefType
);
6423 if(hRefType
!= -1) {
6424 ITypeLib
*pTLib
= NULL
;
6426 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
6428 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
6430 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
6431 TRACE("typeinfo in imported typelib that is already loaded\n");
6432 pTLib
= (ITypeLib
*)ref_type
->pImpTLInfo
->pImpTypeLib
;
6433 ITypeLib2_AddRef(pTLib
);
6436 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6437 result
= LoadRegTypeLib( &ref_type
->pImpTLInfo
->guid
,
6438 ref_type
->pImpTLInfo
->wVersionMajor
,
6439 ref_type
->pImpTLInfo
->wVersionMinor
,
6440 ref_type
->pImpTLInfo
->lcid
,
6443 if(!SUCCEEDED(result
)) {
6444 BSTR libnam
=SysAllocString(ref_type
->pImpTLInfo
->name
);
6445 result
=LoadTypeLib(libnam
, &pTLib
);
6446 SysFreeString(libnam
);
6448 if(SUCCEEDED(result
)) {
6449 ref_type
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
6450 ITypeLib2_AddRef(pTLib
);
6454 if(SUCCEEDED(result
)) {
6455 if(ref_type
->index
== TLB_REF_USE_GUID
)
6456 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
6460 result
= ITypeLib2_GetTypeInfo(pTLib
, ref_type
->index
,
6464 ITypeLib2_Release(pTLib
);
6469 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
6470 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
6474 /* ITypeInfo::AddressOfMember
6476 * Retrieves the addresses of static functions or variables, such as those
6479 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
6480 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
6482 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6488 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
6490 hr
= ITypeInfo_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
6494 module
= LoadLibraryW(dll
);
6497 ERR("couldn't load %s\n", debugstr_w(dll
));
6499 if (entry
) SysFreeString(entry
);
6500 return STG_E_FILENOTFOUND
;
6502 /* FIXME: store library somewhere where we can free it */
6507 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
6508 entryA
= HeapAlloc(GetProcessHeap(), 0, len
);
6509 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
6511 *ppv
= GetProcAddress(module
, entryA
);
6513 ERR("function not found %s\n", debugstr_a(entryA
));
6515 HeapFree(GetProcessHeap(), 0, entryA
);
6519 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
6521 ERR("function not found %d\n", ordinal
);
6525 if (entry
) SysFreeString(entry
);
6528 return TYPE_E_DLLFUNCTIONNOTFOUND
;
6533 /* ITypeInfo::CreateInstance
6535 * Creates a new instance of a type that describes a component object class
6538 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
6539 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
6541 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6545 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
6551 WARN("Not able to aggregate\n");
6552 return CLASS_E_NOAGGREGATION
;
6555 hr
= ITypeInfo_GetTypeAttr(iface
, &pTA
);
6556 if(FAILED(hr
)) return hr
;
6558 if(pTA
->typekind
!= TKIND_COCLASS
)
6560 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
6566 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
6569 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
6570 TRACE("GetActiveObject rets %08x\n", hr
);
6573 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
6574 IUnknown_Release(pUnk
);
6579 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
6580 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
6584 ITypeInfo_ReleaseTypeAttr(iface
, pTA
);
6588 /* ITypeInfo::GetMops
6590 * Retrieves marshalling information.
6592 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
6595 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6596 FIXME("(%p) stub!\n", This
);
6600 /* ITypeInfo::GetContainingTypeLib
6602 * Retrieves the containing type library and the index of the type description
6603 * within that type library.
6605 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
6606 ITypeLib
* *ppTLib
, UINT
*pIndex
)
6608 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6610 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6612 *pIndex
=This
->index
;
6613 TRACE("returning pIndex=%d\n", *pIndex
);
6617 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
6618 ITypeLib2_AddRef(*ppTLib
);
6619 TRACE("returning ppTLib=%p\n", *ppTLib
);
6625 /* ITypeInfo::ReleaseTypeAttr
6627 * Releases a TYPEATTR previously returned by GetTypeAttr.
6630 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
6631 TYPEATTR
* pTypeAttr
)
6633 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6634 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
6635 HeapFree(GetProcessHeap(), 0, pTypeAttr
);
6638 /* ITypeInfo::ReleaseFuncDesc
6640 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6642 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
6644 FUNCDESC
*pFuncDesc
)
6646 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6649 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
6651 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6652 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
6653 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
6655 SysFreeString((BSTR
)pFuncDesc
);
6658 /* ITypeInfo::ReleaseVarDesc
6660 * Releases a VARDESC previously returned by GetVarDesc.
6662 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
6665 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6666 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
6668 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
6669 if (pVarDesc
->varkind
== VAR_CONST
)
6670 VariantClear(pVarDesc
->u
.lpvarValue
);
6671 SysFreeString((BSTR
)pVarDesc
);
6674 /* ITypeInfo2::GetTypeKind
6676 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6679 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
6680 TYPEKIND
*pTypeKind
)
6682 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6683 *pTypeKind
=This
->TypeAttr
.typekind
;
6684 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
6688 /* ITypeInfo2::GetTypeFlags
6690 * Returns the type flags without any allocations. This returns a DWORD type
6691 * flag, which expands the type flags without growing the TYPEATTR (type
6695 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
6697 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6698 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
6699 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
6703 /* ITypeInfo2::GetFuncIndexOfMemId
6704 * Binds to a specific member based on a known DISPID, where the member name
6705 * is not known (for example, when binding to a default member).
6708 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
6709 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
6711 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6712 const TLBFuncDesc
*pFuncInfo
;
6716 for(i
= 0, pFuncInfo
= This
->funclist
; pFuncInfo
; i
++, pFuncInfo
=pFuncInfo
->next
)
6717 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
6723 result
= TYPE_E_ELEMENTNOTFOUND
;
6725 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
6726 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
6730 /* TypeInfo2::GetVarIndexOfMemId
6732 * Binds to a specific member based on a known DISPID, where the member name
6733 * is not known (for example, when binding to a default member).
6736 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
6737 MEMBERID memid
, UINT
*pVarIndex
)
6739 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6740 TLBVarDesc
*pVarInfo
;
6743 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
6744 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
6750 result
= TYPE_E_ELEMENTNOTFOUND
;
6752 TRACE("(%p) memid 0x%08x -> %s\n", This
,
6753 memid
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
6757 /* ITypeInfo2::GetCustData
6759 * Gets the custom data
6761 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
6766 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6767 TLBCustData
*pCData
;
6769 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
6770 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6772 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6776 VariantInit( pVarVal
);
6777 VariantCopy( pVarVal
, &pCData
->data
);
6780 return E_INVALIDARG
; /* FIXME: correct? */
6783 /* ITypeInfo2::GetFuncCustData
6785 * Gets the custom data
6787 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
6793 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6794 TLBCustData
*pCData
=NULL
;
6795 TLBFuncDesc
* pFDesc
;
6797 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
6798 pFDesc
=pFDesc
->next
);
6801 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
6802 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6804 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6807 VariantInit( pVarVal
);
6808 VariantCopy( pVarVal
, &pCData
->data
);
6811 return E_INVALIDARG
; /* FIXME: correct? */
6814 /* ITypeInfo2::GetParamCustData
6816 * Gets the custom data
6818 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
6825 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6826 TLBCustData
*pCData
=NULL
;
6827 TLBFuncDesc
* pFDesc
;
6830 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
6832 if(pFDesc
&& indexParam
<pFDesc
->funcdesc
.cParams
)
6833 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
6834 pCData
= pCData
->next
)
6835 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6837 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6841 VariantInit( pVarVal
);
6842 VariantCopy( pVarVal
, &pCData
->data
);
6845 return E_INVALIDARG
; /* FIXME: correct? */
6848 /* ITypeInfo2::GetVarCustData
6850 * Gets the custom data
6852 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
6858 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6859 TLBCustData
*pCData
=NULL
;
6860 TLBVarDesc
* pVDesc
;
6863 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
6867 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
6869 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6873 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6877 VariantInit( pVarVal
);
6878 VariantCopy( pVarVal
, &pCData
->data
);
6881 return E_INVALIDARG
; /* FIXME: correct? */
6884 /* ITypeInfo2::GetImplCustData
6886 * Gets the custom data
6888 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
6894 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6895 TLBCustData
*pCData
=NULL
;
6896 TLBImplType
* pRDesc
;
6899 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
6903 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
6905 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6909 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6913 VariantInit( pVarVal
);
6914 VariantCopy( pVarVal
, &pCData
->data
);
6917 return E_INVALIDARG
; /* FIXME: correct? */
6920 /* ITypeInfo2::GetDocumentation2
6922 * Retrieves the documentation string, the complete Help file name and path,
6923 * the localization context to use, and the context ID for the library Help
6924 * topic in the Help file.
6927 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
6931 BSTR
*pbstrHelpString
,
6932 DWORD
*pdwHelpStringContext
,
6933 BSTR
*pbstrHelpStringDll
)
6935 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6936 const TLBFuncDesc
*pFDesc
;
6937 const TLBVarDesc
*pVDesc
;
6938 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6939 "HelpStringContext(%p) HelpStringDll(%p)\n",
6940 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
6941 pbstrHelpStringDll
);
6942 /* the help string should be obtained from the helpstringdll,
6943 * using the _DLLGetDocumentation function, based on the supplied
6944 * lcid. Nice to do sometime...
6946 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
6948 *pbstrHelpString
=SysAllocString(This
->Name
);
6949 if(pdwHelpStringContext
)
6950 *pdwHelpStringContext
=This
->dwHelpStringContext
;
6951 if(pbstrHelpStringDll
)
6952 *pbstrHelpStringDll
=
6953 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6955 }else {/* for a member */
6956 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6957 if(pFDesc
->funcdesc
.memid
==memid
){
6959 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
6960 if(pdwHelpStringContext
)
6961 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
6962 if(pbstrHelpStringDll
)
6963 *pbstrHelpStringDll
=
6964 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6967 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
6968 if(pVDesc
->vardesc
.memid
==memid
){
6970 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
6971 if(pdwHelpStringContext
)
6972 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
6973 if(pbstrHelpStringDll
)
6974 *pbstrHelpStringDll
=
6975 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6979 return TYPE_E_ELEMENTNOTFOUND
;
6982 /* ITypeInfo2::GetAllCustData
6984 * Gets all custom data items for the Type info.
6987 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
6989 CUSTDATA
*pCustData
)
6991 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6992 TLBCustData
*pCData
;
6995 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
6997 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
6998 if(pCustData
->prgCustData
){
6999 pCustData
->cCustData
=This
->ctCustData
;
7000 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
7001 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7002 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
7005 ERR(" OUT OF MEMORY!\n");
7006 return E_OUTOFMEMORY
;
7011 /* ITypeInfo2::GetAllFuncCustData
7013 * Gets all custom data items for the specified Function
7016 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
7019 CUSTDATA
*pCustData
)
7021 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7022 TLBCustData
*pCData
;
7023 TLBFuncDesc
* pFDesc
;
7025 TRACE("(%p) index %d\n", This
, index
);
7026 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
7027 pFDesc
=pFDesc
->next
)
7030 pCustData
->prgCustData
=
7031 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
7032 if(pCustData
->prgCustData
){
7033 pCustData
->cCustData
=pFDesc
->ctCustData
;
7034 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
7035 pCData
= pCData
->next
){
7036 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7037 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7041 ERR(" OUT OF MEMORY!\n");
7042 return E_OUTOFMEMORY
;
7046 return TYPE_E_ELEMENTNOTFOUND
;
7049 /* ITypeInfo2::GetAllParamCustData
7051 * Gets all custom data items for the Functions
7054 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
7055 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
7057 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7058 TLBCustData
*pCData
=NULL
;
7059 TLBFuncDesc
* pFDesc
;
7061 TRACE("(%p) index %d\n", This
, indexFunc
);
7062 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
7063 pFDesc
=pFDesc
->next
)
7065 if(pFDesc
&& indexParam
<pFDesc
->funcdesc
.cParams
){
7066 pCustData
->prgCustData
=
7067 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
7068 sizeof(CUSTDATAITEM
));
7069 if(pCustData
->prgCustData
){
7070 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
7071 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
7072 pCData
; i
++, pCData
= pCData
->next
){
7073 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7074 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7078 ERR(" OUT OF MEMORY!\n");
7079 return E_OUTOFMEMORY
;
7083 return TYPE_E_ELEMENTNOTFOUND
;
7086 /* ITypeInfo2::GetAllVarCustData
7088 * Gets all custom data items for the specified Variable
7091 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
7092 UINT index
, CUSTDATA
*pCustData
)
7094 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7095 TLBCustData
*pCData
;
7096 TLBVarDesc
* pVDesc
;
7098 TRACE("(%p) index %d\n", This
, index
);
7099 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
7100 pVDesc
=pVDesc
->next
)
7103 pCustData
->prgCustData
=
7104 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
7105 if(pCustData
->prgCustData
){
7106 pCustData
->cCustData
=pVDesc
->ctCustData
;
7107 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
7108 pCData
= pCData
->next
){
7109 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7110 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7114 ERR(" OUT OF MEMORY!\n");
7115 return E_OUTOFMEMORY
;
7119 return TYPE_E_ELEMENTNOTFOUND
;
7122 /* ITypeInfo2::GetAllImplCustData
7124 * Gets all custom data items for the specified implementation type
7127 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
7130 CUSTDATA
*pCustData
)
7132 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7133 TLBCustData
*pCData
;
7134 TLBImplType
* pRDesc
;
7136 TRACE("(%p) index %d\n", This
, index
);
7137 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
7138 pRDesc
=pRDesc
->next
)
7141 pCustData
->prgCustData
=
7142 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
7143 if(pCustData
->prgCustData
){
7144 pCustData
->cCustData
=pRDesc
->ctCustData
;
7145 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
7146 pCData
= pCData
->next
){
7147 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7148 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7152 ERR(" OUT OF MEMORY!\n");
7153 return E_OUTOFMEMORY
;
7157 return TYPE_E_ELEMENTNOTFOUND
;
7160 static const ITypeInfo2Vtbl tinfvt
=
7163 ITypeInfo_fnQueryInterface
,
7165 ITypeInfo_fnRelease
,
7167 ITypeInfo_fnGetTypeAttr
,
7168 ITypeInfo_fnGetTypeComp
,
7169 ITypeInfo_fnGetFuncDesc
,
7170 ITypeInfo_fnGetVarDesc
,
7171 ITypeInfo_fnGetNames
,
7172 ITypeInfo_fnGetRefTypeOfImplType
,
7173 ITypeInfo_fnGetImplTypeFlags
,
7174 ITypeInfo_fnGetIDsOfNames
,
7176 ITypeInfo_fnGetDocumentation
,
7177 ITypeInfo_fnGetDllEntry
,
7178 ITypeInfo_fnGetRefTypeInfo
,
7179 ITypeInfo_fnAddressOfMember
,
7180 ITypeInfo_fnCreateInstance
,
7181 ITypeInfo_fnGetMops
,
7182 ITypeInfo_fnGetContainingTypeLib
,
7183 ITypeInfo_fnReleaseTypeAttr
,
7184 ITypeInfo_fnReleaseFuncDesc
,
7185 ITypeInfo_fnReleaseVarDesc
,
7187 ITypeInfo2_fnGetTypeKind
,
7188 ITypeInfo2_fnGetTypeFlags
,
7189 ITypeInfo2_fnGetFuncIndexOfMemId
,
7190 ITypeInfo2_fnGetVarIndexOfMemId
,
7191 ITypeInfo2_fnGetCustData
,
7192 ITypeInfo2_fnGetFuncCustData
,
7193 ITypeInfo2_fnGetParamCustData
,
7194 ITypeInfo2_fnGetVarCustData
,
7195 ITypeInfo2_fnGetImplTypeCustData
,
7196 ITypeInfo2_fnGetDocumentation2
,
7197 ITypeInfo2_fnGetAllCustData
,
7198 ITypeInfo2_fnGetAllFuncCustData
,
7199 ITypeInfo2_fnGetAllParamCustData
,
7200 ITypeInfo2_fnGetAllVarCustData
,
7201 ITypeInfo2_fnGetAllImplTypeCustData
,
7204 /******************************************************************************
7205 * CreateDispTypeInfo [OLEAUT32.31]
7207 * Build type information for an object so it can be called through an
7208 * IDispatch interface.
7211 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7212 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7215 * This call allows an objects methods to be accessed through IDispatch, by
7216 * building an ITypeInfo object that IDispatch can use to call through.
7218 HRESULT WINAPI
CreateDispTypeInfo(
7219 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
7220 LCID lcid
, /* [I] Locale Id */
7221 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
7223 ITypeInfoImpl
*pTIClass
, *pTIIface
;
7224 ITypeLibImpl
*pTypeLibImpl
;
7226 TLBFuncDesc
**ppFuncDesc
;
7230 pTypeLibImpl
= TypeLibImpl_Constructor();
7231 if (!pTypeLibImpl
) return E_FAIL
;
7233 pTIIface
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
7234 pTIIface
->pTypeLib
= pTypeLibImpl
;
7235 pTIIface
->index
= 0;
7236 pTIIface
->Name
= NULL
;
7237 pTIIface
->dwHelpContext
= -1;
7238 memset(&pTIIface
->TypeAttr
.guid
, 0, sizeof(GUID
));
7239 pTIIface
->TypeAttr
.lcid
= lcid
;
7240 pTIIface
->TypeAttr
.typekind
= TKIND_INTERFACE
;
7241 pTIIface
->TypeAttr
.wMajorVerNum
= 0;
7242 pTIIface
->TypeAttr
.wMinorVerNum
= 0;
7243 pTIIface
->TypeAttr
.cbAlignment
= 2;
7244 pTIIface
->TypeAttr
.cbSizeInstance
= -1;
7245 pTIIface
->TypeAttr
.cbSizeVft
= -1;
7246 pTIIface
->TypeAttr
.cFuncs
= 0;
7247 pTIIface
->TypeAttr
.cImplTypes
= 0;
7248 pTIIface
->TypeAttr
.cVars
= 0;
7249 pTIIface
->TypeAttr
.wTypeFlags
= 0;
7251 ppFuncDesc
= &pTIIface
->funclist
;
7252 for(func
= 0; func
< pidata
->cMembers
; func
++) {
7253 METHODDATA
*md
= pidata
->pmethdata
+ func
;
7254 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
7255 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
7256 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
7257 (*ppFuncDesc
)->funcdesc
.lprgscode
= NULL
;
7258 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_VIRTUAL
;
7259 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
7260 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
7261 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
7262 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
7263 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
<< 2;
7264 (*ppFuncDesc
)->funcdesc
.cScodes
= 0;
7265 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0;
7266 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
7267 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
7268 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
7269 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
7270 md
->cArgs
* sizeof(ELEMDESC
));
7271 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
7272 md
->cArgs
* sizeof(TLBParDesc
));
7273 for(param
= 0; param
< md
->cArgs
; param
++) {
7274 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
7275 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
7277 (*ppFuncDesc
)->helpcontext
= 0;
7278 (*ppFuncDesc
)->HelpStringContext
= 0;
7279 (*ppFuncDesc
)->HelpString
= NULL
;
7280 (*ppFuncDesc
)->Entry
= NULL
;
7281 (*ppFuncDesc
)->ctCustData
= 0;
7282 (*ppFuncDesc
)->pCustData
= NULL
;
7283 (*ppFuncDesc
)->next
= NULL
;
7284 pTIIface
->TypeAttr
.cFuncs
++;
7285 ppFuncDesc
= &(*ppFuncDesc
)->next
;
7288 dump_TypeInfo(pTIIface
);
7290 pTypeLibImpl
->pTypeInfo
= pTIIface
;
7291 pTypeLibImpl
->TypeInfoCount
++;
7293 pTIClass
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
7294 pTIClass
->pTypeLib
= pTypeLibImpl
;
7295 pTIClass
->index
= 1;
7296 pTIClass
->Name
= NULL
;
7297 pTIClass
->dwHelpContext
= -1;
7298 memset(&pTIClass
->TypeAttr
.guid
, 0, sizeof(GUID
));
7299 pTIClass
->TypeAttr
.lcid
= lcid
;
7300 pTIClass
->TypeAttr
.typekind
= TKIND_COCLASS
;
7301 pTIClass
->TypeAttr
.wMajorVerNum
= 0;
7302 pTIClass
->TypeAttr
.wMinorVerNum
= 0;
7303 pTIClass
->TypeAttr
.cbAlignment
= 2;
7304 pTIClass
->TypeAttr
.cbSizeInstance
= -1;
7305 pTIClass
->TypeAttr
.cbSizeVft
= -1;
7306 pTIClass
->TypeAttr
.cFuncs
= 0;
7307 pTIClass
->TypeAttr
.cImplTypes
= 1;
7308 pTIClass
->TypeAttr
.cVars
= 0;
7309 pTIClass
->TypeAttr
.wTypeFlags
= 0;
7311 pTIClass
->impltypelist
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pTIClass
->impltypelist
));
7312 pTIClass
->impltypelist
->hRef
= 0;
7314 ref
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref
));
7317 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
7318 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
7320 dump_TypeInfo(pTIClass
);
7322 pTIIface
->next
= pTIClass
;
7323 pTypeLibImpl
->TypeInfoCount
++;
7325 *pptinfo
= (ITypeInfo
*)pTIClass
;
7327 ITypeInfo_AddRef(*pptinfo
);
7328 ITypeLib_Release((ITypeLib
*)&pTypeLibImpl
->lpVtbl
);
7334 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
7336 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7338 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
7341 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
7343 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7345 return ITypeInfo_AddRef((ITypeInfo
*)This
);
7348 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
7350 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7352 return ITypeInfo_Release((ITypeInfo
*)This
);
7355 static HRESULT WINAPI
ITypeComp_fnBind(
7360 ITypeInfo
** ppTInfo
,
7361 DESCKIND
* pDescKind
,
7364 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7365 const TLBFuncDesc
*pFDesc
;
7366 const TLBVarDesc
*pVDesc
;
7367 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
7369 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7371 *pDescKind
= DESCKIND_NONE
;
7372 pBindPtr
->lpfuncdesc
= NULL
;
7375 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
7376 if (!strcmpiW(pFDesc
->Name
, szName
)) {
7377 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
7380 /* name found, but wrong flags */
7381 hr
= TYPE_E_TYPEMISMATCH
;
7386 HRESULT hr
= TLB_AllocAndInitFuncDesc(
7388 &pBindPtr
->lpfuncdesc
,
7389 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
7392 *pDescKind
= DESCKIND_FUNCDESC
;
7393 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7394 ITypeInfo_AddRef(*ppTInfo
);
7397 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
7398 if (!strcmpiW(pVDesc
->Name
, szName
)) {
7399 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
7402 *pDescKind
= DESCKIND_VARDESC
;
7403 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7404 ITypeInfo_AddRef(*ppTInfo
);
7409 /* FIXME: search each inherited interface, not just the first */
7410 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypelist
) {
7411 /* recursive search */
7415 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
7418 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
7419 ITypeInfo_Release(pTInfo
);
7423 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7424 ITypeComp_Release(pTComp
);
7427 WARN("Could not search inherited interface!\n");
7429 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
7433 static HRESULT WINAPI
ITypeComp_fnBindType(
7437 ITypeInfo
** ppTInfo
,
7438 ITypeComp
** ppTComp
)
7440 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
7442 /* strange behaviour (does nothing) but like the
7445 if (!ppTInfo
|| !ppTComp
)
7454 static const ITypeCompVtbl tcompvt
=
7457 ITypeComp_fnQueryInterface
,
7459 ITypeComp_fnRelease
,
7462 ITypeComp_fnBindType