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 int 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 structurees */
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_PTR
: sprintf(szVarType
, "ptr to ");
1088 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1090 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1091 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1093 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1094 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1095 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1098 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1102 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1104 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1105 dump_TypeDesc(&edesc
->tdesc
,buf
);
1106 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1107 MESSAGE("\t\tu.paramdesc.wParamFlags");
1108 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1109 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1110 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1111 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1112 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1113 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1114 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1115 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1116 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1118 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1120 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1121 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1122 MESSAGE("Param %d:\n",i
);
1123 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1125 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1126 switch (funcdesc
->funckind
) {
1127 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1128 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1129 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1130 case FUNC_STATIC
: MESSAGE("static");break;
1131 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1132 default: MESSAGE("unknown");break;
1134 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1135 switch (funcdesc
->invkind
) {
1136 case INVOKE_FUNC
: MESSAGE("func");break;
1137 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1138 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1139 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1141 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1142 switch (funcdesc
->callconv
) {
1143 case CC_CDECL
: MESSAGE("cdecl");break;
1144 case CC_PASCAL
: MESSAGE("pascal");break;
1145 case CC_STDCALL
: MESSAGE("stdcall");break;
1146 case CC_SYSCALL
: MESSAGE("syscall");break;
1149 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1150 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1151 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1153 MESSAGE("\telemdescFunc (return value type):\n");
1154 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1157 static const char * const typekind_desc
[] =
1170 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1173 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1174 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1175 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1178 dump_FUNCDESC(&(pfd
->funcdesc
));
1180 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1181 MESSAGE("\tentry: %s\n", (pfd
->Entry
== (void *)-1) ? "invalid" : debugstr_w(pfd
->Entry
));
1183 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
)
1187 dump_TLBFuncDescOne(pfd
);
1191 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
)
1195 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1200 static void dump_TLBImpLib(const TLBImpLib
*import
)
1202 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1203 debugstr_w(import
->name
));
1204 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1205 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1208 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1212 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1214 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1215 if(ref
->index
== -1)
1216 TRACE_(typelib
)("%s\n", debugstr_guid(&(ref
->guid
)));
1218 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1220 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1222 TRACE_(typelib
)("in lib\n");
1223 dump_TLBImpLib(ref
->pImpTLInfo
);
1228 static void dump_TLBImplType(const TLBImplType
* impl
)
1232 "implementing/inheriting interface hRef = %x implflags %x\n",
1233 impl
->hRef
, impl
->implflags
);
1238 static void dump_Variant(const VARIANT
* pvar
)
1242 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1246 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1247 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1249 TRACE(",%p", V_BYREF(pvar
));
1251 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1253 TRACE(",%p", V_ARRAY(pvar
));
1255 else switch (V_TYPE(pvar
))
1257 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1258 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1259 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1260 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1262 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1264 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1265 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1266 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1267 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1268 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1269 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1270 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1271 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1272 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1273 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1274 V_CY(pvar
).s
.Lo
); break;
1276 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1277 TRACE(",<invalid>");
1279 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1280 st
.wHour
, st
.wMinute
, st
.wSecond
);
1284 case VT_USERDEFINED
:
1286 case VT_NULL
: break;
1287 default: TRACE(",?"); break;
1293 static void dump_DispParms(const DISPPARAMS
* pdp
)
1297 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1299 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1301 TRACE("named args:\n");
1302 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1303 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1306 if (pdp
->cArgs
&& pdp
->rgvarg
)
1309 for (index
= 0; index
< pdp
->cArgs
; index
++)
1310 dump_Variant( &pdp
->rgvarg
[index
] );
1314 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1316 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1317 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1318 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1319 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1320 TRACE("fct:%u var:%u impl:%u\n",
1321 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1322 TRACE("wTypeFlags: 0x%04x\n", pty
->TypeAttr
.wTypeFlags
);
1323 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1324 if (pty
->TypeAttr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(pty
->DllName
));
1326 dump_TLBFuncDesc(pty
->funclist
);
1327 dump_TLBVarDesc(pty
->varlist
);
1328 dump_TLBImplType(pty
->impltypelist
);
1331 static void dump_VARDESC(const VARDESC
*v
)
1333 MESSAGE("memid %d\n",v
->memid
);
1334 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1335 MESSAGE("oInst %d\n",v
->u
.oInst
);
1336 dump_ELEMDESC(&(v
->elemdescVar
));
1337 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1338 MESSAGE("varkind %d\n",v
->varkind
);
1341 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1343 /* VT_LPWSTR is largest type that */
1344 /* may appear in type description*/
1345 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1346 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1347 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1348 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1349 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1350 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1354 static void TLB_abort(void)
1358 static void * TLB_Alloc(unsigned size
)
1361 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1363 ERR("cannot allocate memory\n");
1368 static void TLB_Free(void * ptr
)
1370 HeapFree(GetProcessHeap(), 0, ptr
);
1373 /* returns the size required for a deep copy of a typedesc into a
1375 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1379 if (alloc_initial_space
)
1380 size
+= sizeof(TYPEDESC
);
1386 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1389 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1390 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1396 /* deep copy a typedesc into a flat buffer */
1397 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1402 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1411 dest
->u
.lptdesc
= buffer
;
1412 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1415 dest
->u
.lpadesc
= buffer
;
1416 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1417 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1418 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1424 /* free custom data allocated by MSFT_CustData */
1425 static inline void TLB_FreeCustData(TLBCustData
*pCustData
)
1427 TLBCustData
*pCustDataNext
;
1428 for (; pCustData
; pCustData
= pCustDataNext
)
1430 VariantClear(&pCustData
->data
);
1432 pCustDataNext
= pCustData
->next
;
1433 TLB_Free(pCustData
);
1437 /**********************************************************************
1439 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1441 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
1446 static inline void MSFT_Seek(TLBContext
*pcx
, long where
)
1448 if (where
!= DO_NOT_SEEK
)
1450 where
+= pcx
->oStart
;
1451 if (where
> pcx
->length
)
1454 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1462 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1464 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1465 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1467 MSFT_Seek(pcx
, where
);
1468 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1469 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1474 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1479 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1480 FromLEDWords(buffer
, ret
);
1485 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1490 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1491 FromLEWords(buffer
, ret
);
1496 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1498 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1499 memset(pGuid
,0, sizeof(GUID
));
1502 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1503 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1504 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1505 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1506 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1509 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
1511 MSFT_NameIntro niName
;
1515 ERR_(typelib
)("bad offset %d\n", offset
);
1519 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1520 pcx
->pTblDir
->pNametab
.offset
+offset
);
1522 return niName
.hreftype
;
1525 static BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1528 MSFT_NameIntro niName
;
1530 BSTR bstrName
= NULL
;
1534 ERR_(typelib
)("bad offset %d\n", offset
);
1537 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1538 pcx
->pTblDir
->pNametab
.offset
+offset
);
1539 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1540 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1541 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1542 name
[niName
.namelen
& 0xff]='\0';
1544 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1547 /* no invalid characters in string */
1550 bstrName
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1552 /* don't check for invalid character since this has been done previously */
1553 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, bstrName
, lengthInChars
);
1557 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1561 static BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1568 if(offset
<0) return NULL
;
1569 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1570 if(length
<= 0) return 0;
1571 string
=TLB_Alloc(length
+1);
1572 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1573 string
[length
]='\0';
1575 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1576 string
, -1, NULL
, 0);
1578 /* no invalid characters in string */
1581 bstr
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1583 /* don't check for invalid character since this has been done previously */
1584 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, bstr
, lengthInChars
);
1588 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1592 * read a value and fill a VARIANT structure
1594 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1598 TRACE_(typelib
)("\n");
1600 if(offset
<0) { /* data are packed in here */
1601 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1602 V_I4(pVar
) = offset
& 0x3ffffff;
1605 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1606 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1607 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1608 switch (V_VT(pVar
)){
1609 case VT_EMPTY
: /* FIXME: is this right? */
1610 case VT_NULL
: /* FIXME: is this right? */
1611 case VT_I2
: /* this should not happen */
1622 case VT_VOID
: /* FIXME: is this right? */
1630 case VT_DECIMAL
: /* FIXME: is this right? */
1633 /* pointer types with known behaviour */
1636 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1639 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
1642 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
1644 nullPos
= MSFT_Tell(pcx
);
1645 size
= nullPos
- origPos
;
1646 MSFT_Seek(pcx
, origPos
);
1648 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1649 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1650 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1651 /* FIXME: do we need a AtoW conversion here? */
1652 V_UNION(pVar
, bstrVal
[size
])='\0';
1653 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1657 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1664 case VT_USERDEFINED
:
1670 case VT_STREAMED_OBJECT
:
1671 case VT_STORED_OBJECT
:
1672 case VT_BLOB_OBJECT
:
1677 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1681 if(size
>0) /* (big|small) endian correct? */
1682 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1686 * create a linked list with custom data
1688 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1694 TRACE_(typelib
)("\n");
1698 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1699 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1700 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1701 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1702 /* add new custom data at head of the list */
1703 pNew
->next
=*ppCustData
;
1705 offset
= entry
.next
;
1710 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1714 pTd
->vt
=type
& VT_TYPEMASK
;
1716 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1718 if(pTd
->vt
== VT_USERDEFINED
)
1719 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, pTd
->u
.hreftype
);
1721 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1724 static void MSFT_ResolveReferencedTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, TYPEDESC
*lpTypeDesc
)
1726 /* resolve referenced type if any */
1729 switch (lpTypeDesc
->vt
)
1732 lpTypeDesc
= lpTypeDesc
->u
.lptdesc
;
1736 lpTypeDesc
= & (lpTypeDesc
->u
.lpadesc
->tdescElem
);
1739 case VT_USERDEFINED
:
1740 MSFT_DoRefType(pcx
, pTI
->pTypeLib
,
1741 lpTypeDesc
->u
.hreftype
);
1753 MSFT_DoFuncs(TLBContext
* pcx
,
1758 TLBFuncDesc
** pptfd
)
1761 * member information is stored in a data structure at offset
1762 * indicated by the memoffset field of the typeinfo structure
1763 * There are several distinctive parts.
1764 * The first part starts with a field that holds the total length
1765 * of this (first) part excluding this field. Then follow the records,
1766 * for each member there is one record.
1768 * The first entry is always the length of the record (including this
1770 * The rest of the record depends on the type of the member. If there is
1771 * a field indicating the member type (function, variable, interface, etc)
1772 * I have not found it yet. At this time we depend on the information
1773 * in the type info and the usual order how things are stored.
1775 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1778 * Third is an equal sized array with file offsets to the name entry
1781 * The fourth and last (?) part is an array with offsets to the records
1782 * in the first part of this file segment.
1785 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1786 int recoffset
= offset
+ sizeof(INT
);
1788 char *recbuf
= HeapAlloc(GetProcessHeap(), 0, 0xffff);
1789 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1790 TLBFuncDesc
*ptfd_prev
= NULL
;
1792 TRACE_(typelib
)("\n");
1794 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1796 for ( i
= 0; i
< cFuncs
; i
++ )
1798 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1800 /* name, eventually add to a hash table */
1801 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1802 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1804 /* nameoffset is sometimes -1 on the second half of a propget/propput
1805 * pair of functions */
1806 if ((nameoffset
== -1) && (i
> 0))
1807 (*pptfd
)->Name
= SysAllocString(ptfd_prev
->Name
);
1809 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1811 /* read the function information record */
1812 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1814 reclength
&= 0xffff;
1816 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1818 /* do the attributes */
1819 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1822 if ( nrattributes
> 0 )
1824 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1826 if ( nrattributes
> 1 )
1828 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1829 pFuncRec
->OptAttr
[1]) ;
1831 if ( nrattributes
> 2 )
1833 if ( pFuncRec
->FKCCIC
& 0x2000 )
1835 if (HIWORD(pFuncRec
->OptAttr
[2]) != 0)
1836 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec
->OptAttr
[2]);
1837 (*pptfd
)->Entry
= (BSTR
)pFuncRec
->OptAttr
[2];
1841 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1842 pFuncRec
->OptAttr
[2]);
1844 if( nrattributes
> 5 )
1846 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1848 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1851 pFuncRec
->OptAttr
[6],
1852 &(*pptfd
)->pCustData
);
1858 (*pptfd
)->Entry
= (BSTR
)-1;
1863 /* fill the FuncDesc Structure */
1864 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1865 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1867 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1868 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1869 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1870 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1871 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1872 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1873 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1877 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1879 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
);
1881 /* do the parameters/arguments */
1882 if(pFuncRec
->nrargs
)
1885 MSFT_ParameterInfo paraminfo
;
1887 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1888 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1890 (*pptfd
)->pParamDesc
=
1891 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1893 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1894 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1896 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1898 ELEMDESC
*elemdesc
= &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1905 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1908 if (paraminfo
.oName
== -1)
1909 /* this occurs for [propput] or [propget] methods, so
1910 * we should just set the name of the parameter to the
1911 * name of the method. */
1912 (*pptfd
)->pParamDesc
[j
].Name
= SysAllocString((*pptfd
)->Name
);
1914 (*pptfd
)->pParamDesc
[j
].Name
=
1915 MSFT_ReadName( pcx
, paraminfo
.oName
);
1916 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w((*pptfd
)->pParamDesc
[j
].Name
));
1918 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
1921 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
1922 (pFuncRec
->FKCCIC
& 0x1000) )
1924 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1926 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1928 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
1930 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1931 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1933 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1937 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
1939 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1942 pFuncRec
->OptAttr
[7+j
],
1943 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1946 /* SEEK value = jump to offset,
1947 * from there jump to the end of record,
1948 * go back by (j-1) arguments
1950 MSFT_ReadLEDWords( ¶minfo
,
1951 sizeof(MSFT_ParameterInfo
), pcx
,
1952 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1953 * sizeof(MSFT_ParameterInfo
)));
1957 /* scode is not used: archaic win16 stuff FIXME: right? */
1958 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1959 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1962 pptfd
= & ((*pptfd
)->next
);
1963 recoffset
+= reclength
;
1965 HeapFree(GetProcessHeap(), 0, recbuf
);
1968 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1969 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1971 int infolen
, nameoffset
, reclength
;
1973 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1977 TRACE_(typelib
)("\n");
1979 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1980 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1981 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1982 recoffset
+= offset
+sizeof(INT
);
1983 for(i
=0;i
<cVars
;i
++){
1984 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1985 /* name, eventually add to a hash table */
1986 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1987 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1988 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1989 /* read the variable information record */
1990 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1992 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1994 if(reclength
>(6*sizeof(INT
)) )
1995 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1996 if(reclength
>(7*sizeof(INT
)) )
1997 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1998 if(reclength
>(8*sizeof(INT
)) )
1999 if(reclength
>(9*sizeof(INT
)) )
2000 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
2001 /* fill the VarDesc Structure */
2002 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
2003 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2004 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
2005 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
2006 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2007 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
2008 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2009 if(pVarRec
->VarKind
== VAR_CONST
){
2010 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
2011 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
2012 pVarRec
->OffsValue
, pcx
);
2014 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2015 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptvd
)->vardesc
.elemdescVar
.tdesc
);
2016 pptvd
=&((*pptvd
)->next
);
2017 recoffset
+= reclength
;
2020 /* fill in data for a hreftype (offset). When the referenced type is contained
2021 * in the typelib, it's just an (file) offset in the type info base dir.
2022 * If comes from import, it's an offset+1 in the ImpInfo table
2024 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
,
2030 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2032 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
2034 if(ref
->reference
== offset
) return;
2037 ref
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref
));
2038 list_add_tail(&pTL
->ref_list
, &ref
->entry
);
2040 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2041 /* external typelib */
2042 MSFT_ImpInfo impinfo
;
2043 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
2045 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2047 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2048 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2049 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
2050 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
2051 pImpLib
=pImpLib
->next
;
2054 ref
->reference
= offset
;
2055 ref
->pImpTLInfo
= pImpLib
;
2056 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2057 MSFT_ReadGuid(&ref
->guid
, impinfo
.oGuid
, pcx
);
2058 TRACE("importing by guid %s\n", debugstr_guid(&ref
->guid
));
2059 ref
->index
= TLB_REF_USE_GUID
;
2061 ref
->index
= impinfo
.oGuid
;
2063 ERR("Cannot find a reference\n");
2064 ref
->reference
= -1;
2065 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2068 /* in this typelib */
2069 ref
->index
= MSFT_HREFTYPE_INDEX(offset
);
2070 ref
->reference
= offset
;
2071 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
2075 /* process Implemented Interfaces of a com class */
2076 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2080 MSFT_RefRecord refrec
;
2081 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
2083 TRACE_(typelib
)("\n");
2085 for(i
=0;i
<count
;i
++){
2086 if(offset
<0) break; /* paranoia */
2087 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
2088 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2089 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, refrec
.reftype
);
2090 (*ppImpl
)->hRef
= refrec
.reftype
;
2091 (*ppImpl
)->implflags
=refrec
.flags
;
2092 (*ppImpl
)->ctCustData
=
2093 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
2094 offset
=refrec
.onext
;
2095 ppImpl
=&((*ppImpl
)->next
);
2099 * process a typeinfo record
2101 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2104 ITypeLibImpl
* pLibInfo
)
2106 MSFT_TypeInfoBase tiBase
;
2107 ITypeInfoImpl
*ptiRet
;
2109 TRACE_(typelib
)("count=%u\n", count
);
2111 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
2112 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2113 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2115 /* this is where we are coming from */
2116 ptiRet
->pTypeLib
= pLibInfo
;
2117 ptiRet
->index
=count
;
2118 /* fill in the typeattr fields */
2120 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2121 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2122 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2123 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2124 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2125 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2126 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2127 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2128 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2129 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2130 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2131 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2132 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2133 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2134 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2135 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2138 /* IDLDESC idldescType; *//* never saw this one != zero */
2140 /* name, eventually add to a hash table */
2141 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2142 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2143 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2145 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2146 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2147 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2149 if (ptiRet
->TypeAttr
.typekind
== TKIND_MODULE
)
2150 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2152 /* note: InfoType's Help file and HelpStringDll come from the containing
2153 * library. Further HelpString and Docstring appear to be the same thing :(
2156 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2157 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2158 ptiRet
->TypeAttr
.cVars
,
2159 tiBase
.memoffset
, & ptiRet
->funclist
);
2161 if(ptiRet
->TypeAttr
.cVars
>0 )
2162 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2163 ptiRet
->TypeAttr
.cVars
,
2164 tiBase
.memoffset
, & ptiRet
->varlist
);
2165 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2166 switch(ptiRet
->TypeAttr
.typekind
)
2169 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2172 case TKIND_DISPATCH
:
2173 /* This is not -1 when the interface is a non-base dual interface or
2174 when a dispinterface wraps an interface ie the idl 'dispinterface x {interface y;};'.
2175 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2179 if (tiBase
.datatype1
!= -1)
2181 ptiRet
->impltypelist
= TLB_Alloc(sizeof(TLBImplType
));
2182 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2183 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2187 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2188 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2189 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2194 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2196 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2197 debugstr_w(ptiRet
->Name
),
2198 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2199 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2204 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2205 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2206 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2209 static ITypeLibImpl
*tlb_cache_first
;
2210 static CRITICAL_SECTION cache_section
;
2211 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2213 0, 0, &cache_section
,
2214 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2215 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2217 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2220 /****************************************************************************
2223 * find the type of the typelib file and map the typelib resource into
2226 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2227 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2228 static int TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
2230 ITypeLibImpl
*entry
;
2231 int ret
= TYPE_E_CANTLOADLIBRARY
;
2234 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
2238 index_str
= strrchrW(pszFileName
, '\\');
2239 if(index_str
&& *++index_str
!= '\0')
2242 long idx
= strtolW(index_str
, &end_ptr
, 10);
2243 if(*end_ptr
== '\0')
2245 int str_len
= index_str
- pszFileName
- 1;
2247 file
= HeapAlloc(GetProcessHeap(), 0, (str_len
+ 1) * sizeof(WCHAR
));
2248 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
2253 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
2255 if(strchrW(file
, '\\'))
2257 lstrcpyW(pszPath
, file
);
2261 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
2262 pszPath
[len
] = '\\';
2263 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
2267 if(file
!= pszFileName
) HeapFree(GetProcessHeap(), 0, file
);
2269 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
2271 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2272 EnterCriticalSection(&cache_section
);
2273 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2275 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
2277 TRACE("cache hit\n");
2278 *ppTypeLib
= (ITypeLib2
*)entry
;
2279 ITypeLib_AddRef(*ppTypeLib
);
2280 LeaveCriticalSection(&cache_section
);
2284 LeaveCriticalSection(&cache_section
);
2286 /* now actually load and parse the typelib */
2288 hinstDLL
= LoadLibraryExW(pszPath
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2289 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2293 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2294 HRSRC hrsrc
= FindResourceW(hinstDLL
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2297 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2300 LPVOID pBase
= LockResource(hGlobal
);
2301 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2305 /* try to load as incore resource */
2306 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2307 if (dwSignature
== MSFT_SIGNATURE
)
2308 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2309 else if (dwSignature
== SLTG_SIGNATURE
)
2310 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2312 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
2314 FreeResource( hGlobal
);
2317 FreeLibrary(hinstDLL
);
2321 HANDLE hFile
= CreateFileW(pszPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
2322 if (INVALID_HANDLE_VALUE
!= hFile
)
2324 HANDLE hMapping
= CreateFileMappingW( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2327 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
2330 /* retrieve file size */
2331 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
2332 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2334 if (dwSignature
== MSFT_SIGNATURE
)
2335 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2336 else if (dwSignature
== SLTG_SIGNATURE
)
2337 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2339 UnmapViewOfFile(pBase
);
2341 CloseHandle(hMapping
);
2348 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2350 TRACE("adding to cache\n");
2351 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath
)+1) * sizeof(WCHAR
));
2352 lstrcpyW(impl
->path
, pszPath
);
2353 /* We should really canonicalise the path here. */
2354 impl
->index
= index
;
2356 /* FIXME: check if it has added already in the meantime */
2357 EnterCriticalSection(&cache_section
);
2358 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2360 tlb_cache_first
= impl
;
2361 LeaveCriticalSection(&cache_section
);
2364 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
2369 /*================== ITypeLib(2) Methods ===================================*/
2371 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
2373 ITypeLibImpl
* pTypeLibImpl
;
2375 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2376 if (!pTypeLibImpl
) return NULL
;
2378 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2379 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2380 pTypeLibImpl
->ref
= 1;
2382 list_init(&pTypeLibImpl
->ref_list
);
2383 pTypeLibImpl
->dispatch_href
= -1;
2385 return pTypeLibImpl
;
2388 /****************************************************************************
2389 * ITypeLib2_Constructor_MSFT
2391 * loading an MSFT typelib from an in-memory image
2393 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2397 MSFT_Header tlbHeader
;
2398 MSFT_SegDir tlbSegDir
;
2399 ITypeLibImpl
* pTypeLibImpl
;
2401 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
2403 pTypeLibImpl
= TypeLibImpl_Constructor();
2404 if (!pTypeLibImpl
) return NULL
;
2406 /* get pointer to beginning of typelib data */
2410 cx
.pLibInfo
= pTypeLibImpl
;
2411 cx
.length
= dwTLBLength
;
2414 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2415 TRACE_(typelib
)("header:\n");
2416 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2417 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2418 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2421 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
2423 /* there is a small amount of information here until the next important
2425 * the segment directory . Try to calculate the amount of data */
2426 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2428 /* now read the segment directory */
2429 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2430 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2431 cx
.pTblDir
= &tlbSegDir
;
2433 /* just check two entries */
2434 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2436 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2437 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2441 /* now fill our internal data */
2442 /* TLIBATTR fields */
2443 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2445 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2446 /* Windows seems to have zero here, is this correct? */
2447 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2448 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader
.lcid
),0),0);
2450 pTypeLibImpl
->LibAttr
.lcid
= 0;
2452 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2453 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2454 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2455 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2457 /* name, eventually add to a hash table */
2458 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2461 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2462 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2464 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2467 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2468 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2471 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2474 if(tlbHeader
.CustomDataOffset
>= 0)
2476 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2479 /* fill in typedescriptions */
2480 if(tlbSegDir
.pTypdescTab
.length
> 0)
2482 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2484 pTypeLibImpl
->ctTypeDesc
= cTD
;
2485 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2486 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2489 /* FIXME: add several sanity checks here */
2490 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2491 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2493 /* FIXME: check safearray */
2495 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2497 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2499 else if(td
[0] == VT_CARRAY
)
2501 /* array descr table here */
2502 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2504 else if(td
[0] == VT_USERDEFINED
)
2506 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2508 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2511 /* second time around to fill the array subscript info */
2514 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2515 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2517 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2518 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2521 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2523 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2525 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2527 for(j
= 0; j
<td
[2]; j
++)
2529 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2530 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2531 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2532 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2537 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2538 ERR("didn't find array description data\n");
2543 /* imported type libs */
2544 if(tlbSegDir
.pImpFiles
.offset
>0)
2546 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2547 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2550 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2555 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2556 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2557 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2559 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2560 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2561 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2562 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2565 name
= TLB_Alloc(size
+1);
2566 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2567 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
2568 (*ppImpLib
)->name
= TLB_Alloc(len
* sizeof(WCHAR
));
2569 MultiByteToWideChar(CP_ACP
, 0, name
, -1, (*ppImpLib
)->name
, len
);
2572 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2573 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2575 ppImpLib
= &(*ppImpLib
)->next
;
2579 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
2580 if(pTypeLibImpl
->dispatch_href
!= -1)
2581 MSFT_DoRefType(&cx
, pTypeLibImpl
, pTypeLibImpl
->dispatch_href
);
2584 if(tlbHeader
.nrtypeinfos
>= 0 )
2586 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2587 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2590 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
2592 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2594 ppTI
= &((*ppTI
)->next
);
2595 (pTypeLibImpl
->TypeInfoCount
)++;
2599 TRACE("(%p)\n", pTypeLibImpl
);
2600 return (ITypeLib2
*) pTypeLibImpl
;
2604 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
2610 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2611 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2612 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2613 ret
= SysAllocString(nameW
);
2614 HeapFree(GetProcessHeap(), 0, nameW
);
2618 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
2624 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2625 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2629 guid
->Data4
[0] = s
>> 8;
2630 guid
->Data4
[1] = s
& 0xff;
2633 for(i
= 0; i
< 6; i
++) {
2634 memcpy(b
, str
+ 24 + 2 * i
, 2);
2635 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2640 static WORD
SLTG_ReadString(const char *ptr
, BSTR
*pBstr
)
2647 bytelen
= *(const WORD
*)ptr
;
2648 if(bytelen
== 0xffff) return 2;
2649 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2650 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2651 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2652 *pBstr
= SysAllocStringLen(nameW
, len
);
2653 HeapFree(GetProcessHeap(), 0, nameW
);
2657 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
2662 bytelen
= *(const WORD
*)ptr
;
2663 if(bytelen
== 0xffff) return 2;
2664 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2665 memcpy(*str
, ptr
+ 2, bytelen
);
2666 (*str
)[bytelen
] = '\0';
2670 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2672 char *ptr
= pLibBlk
;
2675 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2676 FIXME("libblk magic = %04x\n", w
);
2681 if((w
= *(WORD
*)ptr
) != 0xffff) {
2682 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2687 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2689 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2691 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2694 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2697 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
2698 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
2700 pTypeLibImpl
->LibAttr
.lcid
= 0;
2703 ptr
+= 4; /* skip res12 */
2705 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2708 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2711 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2714 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2715 ptr
+= sizeof(GUID
);
2717 return ptr
- (char*)pLibBlk
;
2720 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
2725 } sltg_ref_lookup_t
;
2727 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
2728 HREFTYPE
*typelib_ref
)
2730 if(typeinfo_ref
< table
->num
)
2732 *typelib_ref
= table
->refs
[typeinfo_ref
];
2736 ERR("Unable to find reference\n");
2741 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
2746 if((*pType
& 0xe00) == 0xe00) {
2748 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2750 pTD
= pTD
->u
.lptdesc
;
2752 switch(*pType
& 0x3f) {
2755 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2757 pTD
= pTD
->u
.lptdesc
;
2760 case VT_USERDEFINED
:
2761 pTD
->vt
= VT_USERDEFINED
;
2762 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
2768 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2771 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2773 pTD
->vt
= VT_CARRAY
;
2774 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2776 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2777 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2778 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2779 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2781 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2787 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2791 pTD
->vt
= VT_SAFEARRAY
;
2792 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2794 pTD
= pTD
->u
.lptdesc
;
2798 pTD
->vt
= *pType
& 0x3f;
2807 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
2808 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
2810 /* Handle [in/out] first */
2811 if((*pType
& 0xc000) == 0xc000)
2812 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2813 else if(*pType
& 0x8000)
2814 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2815 else if(*pType
& 0x4000)
2816 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2818 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2821 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2824 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2826 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
2830 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
2835 TLBRefType
*ref_type
;
2836 sltg_ref_lookup_t
*table
;
2837 HREFTYPE typelib_ref
;
2839 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2840 FIXME("Ref magic = %x\n", pRef
->magic
);
2843 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2845 table
= HeapAlloc(GetProcessHeap(), 0, sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
2846 table
->num
= pRef
->number
>> 3;
2848 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
2850 /* We don't want the first href to be 0 */
2851 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
2853 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2855 unsigned int lib_offs
, type_num
;
2857 ref_type
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref_type
));
2859 name
+= SLTG_ReadStringA(name
, &refname
);
2860 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2861 FIXME("Can't sscanf ref\n");
2862 if(lib_offs
!= 0xffff) {
2863 TLBImpLib
**import
= &pTL
->pImpLibs
;
2866 if((*import
)->offset
== lib_offs
)
2868 import
= &(*import
)->next
;
2871 char fname
[MAX_PATH
+1];
2874 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2876 (*import
)->offset
= lib_offs
;
2877 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2879 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
2880 &(*import
)->wVersionMajor
,
2881 &(*import
)->wVersionMinor
,
2882 &(*import
)->lcid
, fname
) != 4) {
2883 FIXME("can't sscanf ref %s\n",
2884 pNameTable
+ lib_offs
+ 40);
2886 len
= strlen(fname
);
2887 if(fname
[len
-1] != '#')
2888 FIXME("fname = %s\n", fname
);
2889 fname
[len
-1] = '\0';
2890 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2892 ref_type
->pImpTLInfo
= *import
;
2894 /* Store a reference to IDispatch */
2895 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&(*import
)->guid
, &IID_StdOle
) && type_num
== 4)
2896 pTL
->dispatch_href
= typelib_ref
;
2898 } else { /* internal ref */
2899 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
2901 ref_type
->reference
= typelib_ref
;
2902 ref_type
->index
= type_num
;
2904 HeapFree(GetProcessHeap(), 0, refname
);
2905 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
2907 table
->refs
[ref
] = typelib_ref
;
2910 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2911 FIXME("End of ref block magic = %x\n", *name
);
2912 dump_TLBRefType(pTL
);
2916 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2917 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
2919 SLTG_ImplInfo
*info
;
2920 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2921 /* I don't really get this structure, usually it's 0x16 bytes
2922 long, but iuser.tlb contains some that are 0x18 bytes long.
2923 That's ok because we can use the next ptr to jump to the next
2924 one. But how do we know the length of the last one? The WORD
2925 at offs 0x8 might be the clue. For now I'm just assuming that
2926 the last one is the regular 0x16 bytes. */
2928 info
= (SLTG_ImplInfo
*)pBlk
;
2930 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2931 sizeof(**ppImplType
));
2932 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &(*ppImplType
)->hRef
);
2933 (*ppImplType
)->implflags
= info
->impltypeflags
;
2934 pTI
->TypeAttr
.cImplTypes
++;
2935 ppImplType
= &(*ppImplType
)->next
;
2937 if(info
->next
== 0xffff)
2940 FIXME("Interface inheriting more than one interface\n");
2941 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2943 info
++; /* see comment at top of function */
2947 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
2948 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
2950 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2951 BSTR bstrPrevName
= NULL
;
2952 SLTG_Variable
*pItem
;
2957 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
2958 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++) {
2960 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2961 sizeof(**ppVarDesc
));
2962 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2964 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
2965 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
2966 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
2970 if (pItem
->name
== 0xfffe)
2971 (*ppVarDesc
)->Name
= SysAllocString(bstrPrevName
);
2973 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2975 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
2976 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
2978 if (pItem
->flags
& 0x40) {
2979 TRACE_(typelib
)("VAR_DISPATCH\n");
2980 (*ppVarDesc
)->vardesc
.varkind
= VAR_DISPATCH
;
2982 else if (pItem
->flags
& 0x10) {
2983 TRACE_(typelib
)("VAR_CONST\n");
2984 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
2985 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
2987 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
2988 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
2989 *(INT
*)(pBlk
+ pItem
->byte_offs
);
2992 TRACE_(typelib
)("VAR_PERINSTANCE\n");
2993 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2994 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2997 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
2998 (*ppVarDesc
)->vardesc
.wVarFlags
= pItem
->varflags
;
3000 if (pItem
->flags
& 0x80)
3001 (*ppVarDesc
)->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
3003 if(pItem
->flags
& 0x02)
3004 pType
= &pItem
->type
;
3006 pType
= (WORD
*)(pBlk
+ pItem
->type
);
3008 if (pItem
->flags
& ~0xd2)
3009 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xd2);
3011 SLTG_DoElem(pType
, pBlk
,
3012 &(*ppVarDesc
)->vardesc
.elemdescVar
, ref_lookup
);
3014 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
3016 bstrPrevName
= (*ppVarDesc
)->Name
;
3017 ppVarDesc
= &((*ppVarDesc
)->next
);
3019 pTI
->TypeAttr
.cVars
= cVars
;
3022 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
3023 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3025 SLTG_Function
*pFunc
;
3027 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
3029 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
;
3030 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++) {
3035 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3036 sizeof(**ppFuncDesc
));
3038 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
3039 case SLTG_FUNCTION_MAGIC
:
3040 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
3042 case SLTG_DISPATCH_FUNCTION_MAGIC
:
3043 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_DISPATCH
;
3045 case SLTG_STATIC_FUNCTION_MAGIC
:
3046 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_STATIC
;
3049 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
3050 HeapFree(GetProcessHeap(), 0, *ppFuncDesc
);
3054 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
3056 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
3057 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
3058 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
3059 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
3060 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
3061 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
3063 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
3064 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
3066 if(pFunc
->retnextopt
& 0x80)
3067 pType
= &pFunc
->rettype
;
3069 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
3071 SLTG_DoElem(pType
, pBlk
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
, ref_lookup
);
3073 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
3074 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3075 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
3076 (*ppFuncDesc
)->pParamDesc
=
3077 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3078 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
3080 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
3082 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
3083 char *paramName
= pNameTable
+ *pArg
;
3085 /* If arg type follows then paramName points to the 2nd
3086 letter of the name, else the next WORD is an offset to
3087 the arg type and paramName points to the first letter.
3088 So let's take one char off paramName and see if we're
3089 pointing at an alpha-numeric char. However if *pArg is
3090 0xffff or 0xfffe then the param has no name, the former
3091 meaning that the next WORD is the type, the latter
3092 meaning that the next WORD is an offset to the type. */
3097 else if(*pArg
== 0xfffe) {
3101 else if(paramName
[-1] && !isalnum(paramName
[-1]))
3106 if(HaveOffs
) { /* the next word is an offset to type */
3107 pType
= (WORD
*)(pBlk
+ *pArg
);
3108 SLTG_DoElem(pType
, pBlk
,
3109 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3114 pArg
= SLTG_DoElem(pArg
, pBlk
,
3115 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3118 /* Are we an optional param ? */
3119 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
3120 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
3121 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
3124 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
3125 TLB_MultiByteToBSTR(paramName
);
3129 ppFuncDesc
= &((*ppFuncDesc
)->next
);
3130 if(pFunc
->next
== 0xffff) break;
3132 pTI
->TypeAttr
.cFuncs
= cFuncs
;
3135 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
3136 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3137 SLTG_TypeInfoTail
*pTITail
)
3139 char *pFirstItem
, *pNextItem
;
3140 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3142 if(pTIHeader
->href_table
!= 0xffffffff) {
3143 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3147 pFirstItem
= pNextItem
= pBlk
;
3149 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3150 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
3152 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3156 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
3157 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3158 const SLTG_TypeInfoTail
*pTITail
)
3160 char *pFirstItem
, *pNextItem
;
3161 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3163 if(pTIHeader
->href_table
!= 0xffffffff) {
3164 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3168 pFirstItem
= pNextItem
= pBlk
;
3170 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3171 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
3174 if (pTITail
->funcs_off
!= 0xffff)
3175 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3177 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3179 if (TRACE_ON(typelib
))
3180 dump_TLBFuncDesc(pTI
->funclist
);
3183 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
3184 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3185 const SLTG_TypeInfoTail
*pTITail
)
3187 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3190 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3191 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3192 const SLTG_TypeInfoTail
*pTITail
)
3195 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3197 if (pTITail
->simple_alias
) {
3198 /* if simple alias, no more processing required */
3199 pTI
->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3203 if(pTIHeader
->href_table
!= 0xffffffff) {
3204 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3208 /* otherwise it is an offset to a type */
3209 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
3211 SLTG_DoType(pType
, pBlk
, &pTI
->TypeAttr
.tdescAlias
, ref_lookup
);
3213 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3216 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3217 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3218 const SLTG_TypeInfoTail
*pTITail
)
3220 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3221 if (pTIHeader
->href_table
!= 0xffffffff)
3222 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3225 if (pTITail
->vars_off
!= 0xffff)
3226 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3228 if (pTITail
->funcs_off
!= 0xffff)
3229 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3231 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3232 * of dispinterface functons including the IDispatch ones, so
3233 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3234 pTI
->TypeAttr
.cbSizeVft
= pTI
->TypeAttr
.cFuncs
* sizeof(void *);
3236 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3237 if (TRACE_ON(typelib
))
3238 dump_TLBFuncDesc(pTI
->funclist
);
3241 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3242 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3243 const SLTG_TypeInfoTail
*pTITail
)
3245 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3248 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
3249 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3250 const SLTG_TypeInfoTail
*pTITail
)
3252 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3253 if (pTIHeader
->href_table
!= 0xffffffff)
3254 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3257 if (pTITail
->vars_off
!= 0xffff)
3258 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3260 if (pTITail
->funcs_off
!= 0xffff)
3261 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3262 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3265 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3266 managable copy of it into this */
3279 } SLTG_InternalOtherTypeInfo
;
3281 /****************************************************************************
3282 * ITypeLib2_Constructor_SLTG
3284 * loading a SLTG typelib from an in-memory image
3286 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3288 ITypeLibImpl
*pTypeLibImpl
;
3289 SLTG_Header
*pHeader
;
3290 SLTG_BlkEntry
*pBlkEntry
;
3294 LPVOID pBlk
, pFirstBlk
;
3295 SLTG_LibBlk
*pLibBlk
;
3296 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3297 char *pAfterOTIBlks
= NULL
;
3298 char *pNameTable
, *ptr
;
3301 ITypeInfoImpl
**ppTypeInfoImpl
;
3303 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3306 pTypeLibImpl
= TypeLibImpl_Constructor();
3307 if (!pTypeLibImpl
) return NULL
;
3311 TRACE_(typelib
)("header:\n");
3312 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
3313 pHeader
->nrOfFileBlks
);
3314 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3315 FIXME("Header type magic 0x%08x not supported.\n",
3316 pHeader
->SLTG_magic
);
3320 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3321 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3323 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3324 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3326 /* Next we have a magic block */
3327 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3329 /* Let's see if we're still in sync */
3330 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3331 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3332 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3335 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3336 sizeof(SLTG_DIR_MAGIC
))) {
3337 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
3341 pIndex
= (SLTG_Index
*)(pMagic
+1);
3343 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3345 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
3347 /* We'll set up a ptr to the main library block, which is the last one. */
3349 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3350 pBlkEntry
[order
].next
!= 0;
3351 order
= pBlkEntry
[order
].next
- 1, i
++) {
3352 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3356 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3358 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3363 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3365 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3366 sizeof(*pOtherTypeInfoBlks
) *
3367 pTypeLibImpl
->TypeInfoCount
);
3370 ptr
= (char*)pLibBlk
+ len
;
3372 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3376 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3378 w
= *(WORD
*)(ptr
+ 2);
3381 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3383 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3384 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3386 w
= *(WORD
*)(ptr
+ 4 + len
);
3388 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3390 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3392 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3393 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3395 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3396 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3397 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3399 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3401 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3404 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3405 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3406 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3407 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3408 len
+= sizeof(SLTG_OtherTypeInfo
);
3412 pAfterOTIBlks
= ptr
;
3414 /* Skip this WORD and get the next DWORD */
3415 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3417 /* Now add this to pLibBLk look at what we're pointing at and
3418 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3419 dust and we should be pointing at the beginning of the name
3422 pNameTable
= (char*)pLibBlk
+ len
;
3424 switch(*(WORD
*)pNameTable
) {
3431 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3435 pNameTable
+= 0x216;
3439 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3441 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3444 /* Hopefully we now have enough ptrs set up to actually read in
3445 some TypeInfos. It's not clear which order to do them in, so
3446 I'll just follow the links along the BlkEntry chain and read
3447 them in the order in which they are in the file */
3449 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3451 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3452 pBlkEntry
[order
].next
!= 0;
3453 order
= pBlkEntry
[order
].next
- 1, i
++) {
3455 SLTG_TypeInfoHeader
*pTIHeader
;
3456 SLTG_TypeInfoTail
*pTITail
;
3457 SLTG_MemberHeader
*pMemHeader
;
3459 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3460 pOtherTypeInfoBlks
[i
].index_name
)) {
3461 FIXME("Index strings don't match\n");
3466 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3467 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3470 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3471 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
3473 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3474 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3475 (*ppTypeInfoImpl
)->index
= i
;
3476 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3477 pOtherTypeInfoBlks
[i
].name_offs
+
3479 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3480 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3482 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3483 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3484 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3485 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3486 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3488 if((pTIHeader
->typeflags1
& 7) != 2)
3489 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3490 if(pTIHeader
->typeflags3
!= 2)
3491 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3493 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3494 debugstr_w((*ppTypeInfoImpl
)->Name
),
3495 typekind_desc
[pTIHeader
->typekind
],
3496 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3497 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3499 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
3501 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
3503 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3504 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3505 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3507 switch(pTIHeader
->typekind
) {
3509 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3510 pTIHeader
, pTITail
);
3514 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3515 pTIHeader
, pTITail
);
3518 case TKIND_INTERFACE
:
3519 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3520 pTIHeader
, pTITail
);
3524 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3525 pTIHeader
, pTITail
);
3529 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3530 pTIHeader
, pTITail
);
3533 case TKIND_DISPATCH
:
3534 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3535 pTIHeader
, pTITail
);
3539 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3540 pTIHeader
, pTITail
);
3544 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3549 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3550 but we've already set those */
3551 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3566 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3567 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3570 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3571 FIXME("Somehow processed %d TypeInfos\n", i
);
3575 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3576 return (ITypeLib2
*)pTypeLibImpl
;
3579 /* ITypeLib::QueryInterface
3581 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3586 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3588 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3591 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3592 IsEqualIID(riid
,&IID_ITypeLib
)||
3593 IsEqualIID(riid
,&IID_ITypeLib2
))
3600 ITypeLib2_AddRef(iface
);
3601 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3604 TRACE("-- Interface: E_NOINTERFACE\n");
3605 return E_NOINTERFACE
;
3610 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3612 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3613 ULONG ref
= InterlockedIncrement(&This
->ref
);
3615 TRACE("(%p)->ref was %u\n",This
, ref
- 1);
3620 /* ITypeLib::Release
3622 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3624 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3625 ULONG ref
= InterlockedDecrement(&This
->ref
);
3627 TRACE("(%p)->(%u)\n",This
, ref
);
3631 TLBImpLib
*pImpLib
, *pImpLibNext
;
3632 TLBCustData
*pCustData
, *pCustDataNext
;
3633 TLBRefType
*ref_type
;
3637 /* remove cache entry */
3640 TRACE("removing from cache list\n");
3641 EnterCriticalSection(&cache_section
);
3642 if (This
->next
) This
->next
->prev
= This
->prev
;
3643 if (This
->prev
) This
->prev
->next
= This
->next
;
3644 else tlb_cache_first
= This
->next
;
3645 LeaveCriticalSection(&cache_section
);
3646 HeapFree(GetProcessHeap(), 0, This
->path
);
3648 TRACE(" destroying ITypeLib(%p)\n",This
);
3652 SysFreeString(This
->Name
);
3656 if (This
->DocString
)
3658 SysFreeString(This
->DocString
);
3659 This
->DocString
= NULL
;
3664 SysFreeString(This
->HelpFile
);
3665 This
->HelpFile
= NULL
;
3668 if (This
->HelpStringDll
)
3670 SysFreeString(This
->HelpStringDll
);
3671 This
->HelpStringDll
= NULL
;
3674 for (pCustData
= This
->pCustData
; pCustData
; pCustData
= pCustDataNext
)
3676 VariantClear(&pCustData
->data
);
3678 pCustDataNext
= pCustData
->next
;
3679 TLB_Free(pCustData
);
3682 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
3683 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
3684 TLB_Free(This
->pTypeDesc
[i
].u
.lpadesc
);
3686 TLB_Free(This
->pTypeDesc
);
3688 for (pImpLib
= This
->pImpLibs
; pImpLib
; pImpLib
= pImpLibNext
)
3690 if (pImpLib
->pImpTypeLib
)
3691 ITypeLib_Release((ITypeLib
*)pImpLib
->pImpTypeLib
);
3692 TLB_Free(pImpLib
->name
);
3694 pImpLibNext
= pImpLib
->next
;
3698 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
3700 list_remove(&ref_type
->entry
);
3704 if (This
->pTypeInfo
) /* can be NULL */
3705 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3706 HeapFree(GetProcessHeap(),0,This
);
3713 /* ITypeLib::GetTypeInfoCount
3715 * Returns the number of type descriptions in the type library
3717 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3719 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3720 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3721 return This
->TypeInfoCount
;
3724 /* ITypeLib::GetTypeInfo
3726 * retrieves the specified type description in the library.
3728 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3731 ITypeInfo
**ppTInfo
)
3735 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3736 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3738 TRACE("(%p)->(index=%d)\n", This
, index
);
3740 if (!ppTInfo
) return E_INVALIDARG
;
3742 /* search element n in list */
3743 for(i
=0; i
< index
; i
++)
3745 pTypeInfo
= pTypeInfo
->next
;
3748 TRACE("-- element not found\n");
3749 return TYPE_E_ELEMENTNOTFOUND
;
3753 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3755 ITypeInfo_AddRef(*ppTInfo
);
3756 TRACE("-- found (%p)\n",*ppTInfo
);
3761 /* ITypeLibs::GetTypeInfoType
3763 * Retrieves the type of a type description.
3765 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3770 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3772 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3774 if (ITypeLib2_fnGetTypeInfoCount(iface
) < index
+ 1)
3775 return TYPE_E_ELEMENTNOTFOUND
;
3777 TRACE("(%p) index %d\n", This
, index
);
3779 if(!pTKind
) return E_INVALIDARG
;
3781 /* search element n in list */
3782 for(i
=0; i
< index
; i
++)
3786 TRACE("-- element not found\n");
3787 return TYPE_E_ELEMENTNOTFOUND
;
3789 pTInfo
= pTInfo
->next
;
3792 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3793 TRACE("-- found Type (%d)\n", *pTKind
);
3797 /* ITypeLib::GetTypeInfoOfGuid
3799 * Retrieves the type description that corresponds to the specified GUID.
3802 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3805 ITypeInfo
**ppTInfo
)
3807 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3808 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3810 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3814 WARN("-- element not found\n");
3815 return TYPE_E_ELEMENTNOTFOUND
;
3818 /* search linked list for guid */
3819 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3821 pTypeInfo
= pTypeInfo
->next
;
3825 /* end of list reached */
3826 WARN("-- element not found\n");
3827 return TYPE_E_ELEMENTNOTFOUND
;
3831 TRACE("-- found (%p, %s)\n",
3833 debugstr_w(pTypeInfo
->Name
));
3835 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3836 ITypeInfo_AddRef(*ppTInfo
);
3840 /* ITypeLib::GetLibAttr
3842 * Retrieves the structure that contains the library's attributes.
3845 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3847 LPTLIBATTR
*ppTLibAttr
)
3849 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3850 TRACE("(%p)\n",This
);
3851 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3852 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3856 /* ITypeLib::GetTypeComp
3858 * Enables a client compiler to bind to a library's types, variables,
3859 * constants, and global functions.
3862 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3864 ITypeComp
**ppTComp
)
3866 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3868 TRACE("(%p)->(%p)\n",This
,ppTComp
);
3869 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
3870 ITypeComp_AddRef(*ppTComp
);
3875 /* ITypeLib::GetDocumentation
3877 * Retrieves the library's documentation string, the complete Help file name
3878 * and path, and the context identifier for the library Help topic in the Help
3881 * On a successful return all non-null BSTR pointers will have been set,
3884 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3888 BSTR
*pBstrDocString
,
3889 DWORD
*pdwHelpContext
,
3890 BSTR
*pBstrHelpFile
)
3892 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3894 HRESULT result
= E_INVALIDARG
;
3899 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3901 pBstrName
, pBstrDocString
,
3902 pdwHelpContext
, pBstrHelpFile
);
3906 /* documentation for the typelib */
3911 if(!(*pBstrName
= SysAllocString(This
->Name
)))
3919 if (This
->DocString
)
3921 if(!(*pBstrDocString
= SysAllocString(This
->DocString
)))
3924 else if (This
->Name
)
3926 if(!(*pBstrDocString
= SysAllocString(This
->Name
)))
3930 *pBstrDocString
= NULL
;
3934 *pdwHelpContext
= This
->dwHelpContext
;
3940 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
)))
3944 *pBstrHelpFile
= NULL
;
3951 /* for a typeinfo */
3952 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3954 if(SUCCEEDED(result
))
3956 result
= ITypeInfo_GetDocumentation(pTInfo
,
3960 pdwHelpContext
, pBstrHelpFile
);
3962 ITypeInfo_Release(pTInfo
);
3967 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3969 if (pBstrName
) SysFreeString (*pBstrName
);
3971 return STG_E_INSUFFICIENTMEMORY
;
3976 * Indicates whether a passed-in string contains the name of a type or member
3977 * described in the library.
3980 static HRESULT WINAPI
ITypeLib2_fnIsName(
3986 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3987 ITypeInfoImpl
*pTInfo
;
3988 TLBFuncDesc
*pFInfo
;
3991 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
3993 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3997 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3998 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3999 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
4000 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4001 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
4002 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
4003 goto ITypeLib2_fnIsName_exit
;
4005 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
4006 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4011 ITypeLib2_fnIsName_exit
:
4012 TRACE("(%p)slow! search for %s: %s found!\n", This
,
4013 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
4018 /* ITypeLib::FindName
4020 * Finds occurrences of a type description in a type library. This may be used
4021 * to quickly verify that a name exists in a type library.
4024 static HRESULT WINAPI
ITypeLib2_fnFindName(
4028 ITypeInfo
**ppTInfo
,
4032 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4033 ITypeInfoImpl
*pTInfo
;
4034 TLBFuncDesc
*pFInfo
;
4037 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
4039 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
4040 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4041 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
4042 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4043 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++) {
4044 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
4045 goto ITypeLib2_fnFindName_exit
;
4048 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
4049 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4051 ITypeLib2_fnFindName_exit
:
4052 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
4053 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
4056 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4057 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
4064 /* ITypeLib::ReleaseTLibAttr
4066 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4069 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
4071 TLIBATTR
*pTLibAttr
)
4073 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4074 TRACE("freeing (%p)\n",This
);
4075 HeapFree(GetProcessHeap(),0,pTLibAttr
);
4079 /* ITypeLib2::GetCustData
4081 * gets the custom data
4083 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
4088 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4089 TLBCustData
*pCData
;
4091 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
4093 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4096 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4100 VariantInit( pVarVal
);
4101 VariantCopy( pVarVal
, &pCData
->data
);
4104 return E_INVALIDARG
; /* FIXME: correct? */
4107 /* ITypeLib2::GetLibStatistics
4109 * Returns statistics about a type library that are required for efficient
4110 * sizing of hash tables.
4113 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
4115 ULONG
*pcUniqueNames
,
4116 ULONG
*pcchUniqueNames
)
4118 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4120 FIXME("(%p): stub!\n", This
);
4122 if(pcUniqueNames
) *pcUniqueNames
=1;
4123 if(pcchUniqueNames
) *pcchUniqueNames
=1;
4127 /* ITypeLib2::GetDocumentation2
4129 * Retrieves the library's documentation string, the complete Help file name
4130 * and path, the localization context to use, and the context ID for the
4131 * library Help topic in the Help file.
4134 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
4138 BSTR
*pbstrHelpString
,
4139 DWORD
*pdwHelpStringContext
,
4140 BSTR
*pbstrHelpStringDll
)
4142 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4146 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
4148 /* the help string should be obtained from the helpstringdll,
4149 * using the _DLLGetDocumentation function, based on the supplied
4150 * lcid. Nice to do sometime...
4154 /* documentation for the typelib */
4156 *pbstrHelpString
=SysAllocString(This
->DocString
);
4157 if(pdwHelpStringContext
)
4158 *pdwHelpStringContext
=This
->dwHelpContext
;
4159 if(pbstrHelpStringDll
)
4160 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
4166 /* for a typeinfo */
4167 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
4169 if(SUCCEEDED(result
))
4171 ITypeInfo2
* pTInfo2
;
4172 result
= ITypeInfo_QueryInterface(pTInfo
,
4174 (LPVOID
*) &pTInfo2
);
4176 if(SUCCEEDED(result
))
4178 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
4182 pdwHelpStringContext
,
4183 pbstrHelpStringDll
);
4185 ITypeInfo2_Release(pTInfo2
);
4188 ITypeInfo_Release(pTInfo
);
4194 /* ITypeLib2::GetAllCustData
4196 * Gets all custom data items for the library.
4199 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
4201 CUSTDATA
*pCustData
)
4203 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4204 TLBCustData
*pCData
;
4206 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
4207 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
4208 if(pCustData
->prgCustData
){
4209 pCustData
->cCustData
=This
->ctCustData
;
4210 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
4211 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4212 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
4215 ERR(" OUT OF MEMORY!\n");
4216 return E_OUTOFMEMORY
;
4221 static const ITypeLib2Vtbl tlbvt
= {
4222 ITypeLib2_fnQueryInterface
,
4224 ITypeLib2_fnRelease
,
4225 ITypeLib2_fnGetTypeInfoCount
,
4226 ITypeLib2_fnGetTypeInfo
,
4227 ITypeLib2_fnGetTypeInfoType
,
4228 ITypeLib2_fnGetTypeInfoOfGuid
,
4229 ITypeLib2_fnGetLibAttr
,
4230 ITypeLib2_fnGetTypeComp
,
4231 ITypeLib2_fnGetDocumentation
,
4233 ITypeLib2_fnFindName
,
4234 ITypeLib2_fnReleaseTLibAttr
,
4236 ITypeLib2_fnGetCustData
,
4237 ITypeLib2_fnGetLibStatistics
,
4238 ITypeLib2_fnGetDocumentation2
,
4239 ITypeLib2_fnGetAllCustData
4243 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4245 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4247 return ITypeLib2_QueryInterface((ITypeLib
*)This
, riid
, ppv
);
4250 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4252 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4254 return ITypeLib2_AddRef((ITypeLib2
*)This
);
4257 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4259 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4261 return ITypeLib2_Release((ITypeLib2
*)This
);
4264 static HRESULT WINAPI
ITypeLibComp_fnBind(
4269 ITypeInfo
** ppTInfo
,
4270 DESCKIND
* pDescKind
,
4273 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4274 ITypeInfoImpl
*pTypeInfo
;
4276 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4278 *pDescKind
= DESCKIND_NONE
;
4279 pBindPtr
->lptcomp
= NULL
;
4282 for (pTypeInfo
= This
->pTypeInfo
; pTypeInfo
; pTypeInfo
= pTypeInfo
->next
)
4284 TRACE("testing %s\n", debugstr_w(pTypeInfo
->Name
));
4286 /* FIXME: check wFlags here? */
4287 /* FIXME: we should use a hash table to look this info up using lHash
4288 * instead of an O(n) search */
4289 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
) ||
4290 (pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
))
4292 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
, szName
))
4294 *pDescKind
= DESCKIND_TYPECOMP
;
4295 pBindPtr
->lptcomp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4296 ITypeComp_AddRef(pBindPtr
->lptcomp
);
4297 TRACE("module or enum: %s\n", debugstr_w(szName
));
4302 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
) ||
4303 (pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
))
4305 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4308 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4309 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
4311 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
4316 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_COCLASS
) &&
4317 (pTypeInfo
->TypeAttr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
4319 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4321 ITypeInfo
*subtypeinfo
;
4323 DESCKIND subdesckind
;
4325 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
4326 &subtypeinfo
, &subdesckind
, &subbindptr
);
4327 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
4329 TYPEDESC tdesc_appobject
=
4332 (TYPEDESC
*)pTypeInfo
->hreftype
4336 const VARDESC vardesc_appobject
=
4339 NULL
, /* lpstrSchema */
4354 VAR_STATIC
/* varkind */
4357 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
4359 /* cleanup things filled in by Bind call so we can put our
4360 * application object data in there instead */
4361 switch (subdesckind
)
4363 case DESCKIND_FUNCDESC
:
4364 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
4366 case DESCKIND_VARDESC
:
4367 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
4372 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
4374 if (pTypeInfo
->hreftype
== -1)
4375 FIXME("no hreftype for interface %p\n", pTypeInfo
);
4377 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
4381 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
4382 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
4383 ITypeInfo_AddRef(*ppTInfo
);
4389 TRACE("name not found %s\n", debugstr_w(szName
));
4393 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4397 ITypeInfo
** ppTInfo
,
4398 ITypeComp
** ppTComp
)
4400 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4404 static const ITypeCompVtbl tlbtcvt
=
4407 ITypeLibComp_fnQueryInterface
,
4408 ITypeLibComp_fnAddRef
,
4409 ITypeLibComp_fnRelease
,
4411 ITypeLibComp_fnBind
,
4412 ITypeLibComp_fnBindType
4415 /*================== ITypeInfo(2) Methods ===================================*/
4416 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
4418 ITypeInfoImpl
* pTypeInfoImpl
;
4420 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4423 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4424 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4425 pTypeInfoImpl
->ref
=1;
4426 pTypeInfoImpl
->hreftype
= -1;
4427 pTypeInfoImpl
->TypeAttr
.memidConstructor
= MEMBERID_NIL
;
4428 pTypeInfoImpl
->TypeAttr
.memidDestructor
= MEMBERID_NIL
;
4430 TRACE("(%p)\n", pTypeInfoImpl
);
4431 return (ITypeInfo2
*) pTypeInfoImpl
;
4434 /* ITypeInfo::QueryInterface
4436 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4441 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4443 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4446 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4447 IsEqualIID(riid
,&IID_ITypeInfo
)||
4448 IsEqualIID(riid
,&IID_ITypeInfo2
))
4452 ITypeInfo_AddRef(iface
);
4453 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4456 TRACE("-- Interface: E_NOINTERFACE\n");
4457 return E_NOINTERFACE
;
4460 /* ITypeInfo::AddRef
4462 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4464 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4465 ULONG ref
= InterlockedIncrement(&This
->ref
);
4467 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4469 TRACE("(%p)->ref is %u\n",This
, ref
);
4473 /* ITypeInfo::Release
4475 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
4477 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4478 ULONG ref
= InterlockedDecrement(&This
->ref
);
4480 TRACE("(%p)->(%u)\n",This
, ref
);
4483 /* We don't release ITypeLib when ref=0 because
4484 it means that function is called by ITypeLib2_Release */
4485 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
4487 TLBFuncDesc
*pFInfo
, *pFInfoNext
;
4488 TLBVarDesc
*pVInfo
, *pVInfoNext
;
4489 TLBImplType
*pImpl
, *pImplNext
;
4491 TRACE("destroying ITypeInfo(%p)\n",This
);
4493 if (This
->no_free_data
)
4498 SysFreeString(This
->Name
);
4502 if (This
->DocString
)
4504 SysFreeString(This
->DocString
);
4505 This
->DocString
= 0;
4510 SysFreeString(This
->DllName
);
4514 for (pFInfo
= This
->funclist
; pFInfo
; pFInfo
= pFInfoNext
)
4517 for(i
= 0;i
< pFInfo
->funcdesc
.cParams
; i
++)
4519 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[i
];
4520 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4522 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
4523 TLB_Free(elemdesc
->u
.paramdesc
.pparamdescex
);
4525 SysFreeString(pFInfo
->pParamDesc
[i
].Name
);
4527 TLB_Free(pFInfo
->funcdesc
.lprgelemdescParam
);
4528 TLB_Free(pFInfo
->pParamDesc
);
4529 TLB_FreeCustData(pFInfo
->pCustData
);
4530 if (HIWORD(pFInfo
->Entry
) != 0 && pFInfo
->Entry
!= (BSTR
)-1)
4531 SysFreeString(pFInfo
->Entry
);
4532 SysFreeString(pFInfo
->HelpString
);
4533 SysFreeString(pFInfo
->Name
);
4535 pFInfoNext
= pFInfo
->next
;
4538 for (pVInfo
= This
->varlist
; pVInfo
; pVInfo
= pVInfoNext
)
4540 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
4542 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
4543 TLB_Free(pVInfo
->vardesc
.u
.lpvarValue
);
4545 TLB_FreeCustData(pVInfo
->pCustData
);
4546 SysFreeString(pVInfo
->Name
);
4547 pVInfoNext
= pVInfo
->next
;
4550 for(pImpl
= This
->impltypelist
; pImpl
; pImpl
= pImplNext
)
4552 TLB_FreeCustData(pImpl
->pCustData
);
4553 pImplNext
= pImpl
->next
;
4556 TLB_FreeCustData(This
->pCustData
);
4561 ITypeInfo_Release((ITypeInfo
*)This
->next
);
4564 HeapFree(GetProcessHeap(),0,This
);
4570 /* ITypeInfo::GetTypeAttr
4572 * Retrieves a TYPEATTR structure that contains the attributes of the type
4576 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
4577 LPTYPEATTR
*ppTypeAttr
)
4579 const ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4582 TRACE("(%p)\n",This
);
4584 size
= sizeof(**ppTypeAttr
);
4585 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
4586 size
+= TLB_SizeTypeDesc(&This
->TypeAttr
.tdescAlias
, FALSE
);
4588 *ppTypeAttr
= HeapAlloc(GetProcessHeap(), 0, size
);
4590 return E_OUTOFMEMORY
;
4592 memcpy(*ppTypeAttr
, &This
->TypeAttr
, sizeof(**ppTypeAttr
));
4594 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
4595 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
4596 &This
->TypeAttr
.tdescAlias
, (void *)(*ppTypeAttr
+ 1));
4598 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
4599 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ 4; /* This should include all the inherited
4601 (*ppTypeAttr
)->cbSizeVft
= 28; /* This is always the size of IDispatch's vtbl */
4602 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
4607 /* ITypeInfo::GetTypeComp
4609 * Retrieves the ITypeComp interface for the type description, which enables a
4610 * client compiler to bind to the type description's members.
4613 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
4614 ITypeComp
* *ppTComp
)
4616 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4618 TRACE("(%p)->(%p)\n", This
, ppTComp
);
4620 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4621 ITypeComp_AddRef(*ppTComp
);
4625 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
4627 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
4628 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4629 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
4633 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
4635 memcpy(dest
, src
, sizeof(ELEMDESC
));
4636 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
4637 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4639 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
4640 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
4641 *buffer
+= sizeof(PARAMDESCEX
);
4642 memcpy(pparamdescex_dest
, pparamdescex_src
, sizeof(PARAMDESCEX
));
4643 VariantInit(&pparamdescex_dest
->varDefaultValue
);
4644 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
4645 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
4648 dest
->u
.paramdesc
.pparamdescex
= NULL
;
4652 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
4654 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4655 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
4658 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
4662 SIZE_T size
= sizeof(*src
);
4666 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
4667 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
4668 for (i
= 0; i
< src
->cParams
; i
++)
4670 size
+= sizeof(ELEMDESC
);
4671 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
4674 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
4675 if (!dest
) return E_OUTOFMEMORY
;
4677 memcpy(dest
, src
, sizeof(FUNCDESC
));
4678 if (dispinterface
) /* overwrite funckind */
4679 dest
->funckind
= FUNC_DISPATCH
;
4680 buffer
= (char *)(dest
+ 1);
4682 dest
->lprgscode
= (SCODE
*)buffer
;
4683 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
4684 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
4686 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
4689 SysFreeString((BSTR
)dest
);
4693 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
4694 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
4695 for (i
= 0; i
< src
->cParams
; i
++)
4697 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
4703 /* undo the above actions */
4704 for (i
= i
- 1; i
>= 0; i
--)
4705 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
4706 TLB_FreeElemDesc(&dest
->elemdescFunc
);
4707 SysFreeString((BSTR
)dest
);
4711 /* special treatment for dispinterfaces: this makes functions appear
4712 * to return their [retval] value when it is really returning an
4714 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
4716 if (dest
->cParams
&&
4717 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
4719 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
4720 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
4722 ERR("elemdesc should have started with VT_PTR instead of:\n");
4724 dump_ELEMDESC(elemdesc
);
4725 return E_UNEXPECTED
;
4728 /* copy last parameter to the return value. we are using a flat
4729 * buffer so there is no danger of leaking memory in
4731 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
4733 /* remove the last parameter */
4737 /* otherwise this function is made to appear to have no return
4739 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
4747 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
4749 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4750 const TLBFuncDesc
*pFDesc
;
4753 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
4758 *ppFuncDesc
= &pFDesc
->funcdesc
;
4762 return TYPE_E_ELEMENTNOTFOUND
;
4765 /* internal function to make the inherited interfaces' methods appear
4766 * part of the interface */
4767 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
4768 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
4770 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4772 UINT implemented_funcs
= 0;
4777 *hrefoffset
= DISPATCH_HREF_OFFSET
;
4779 if(This
->impltypelist
)
4781 ITypeInfo
*pSubTypeInfo
;
4784 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pSubTypeInfo
);
4788 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
4791 &sub_funcs
, hrefoffset
);
4792 implemented_funcs
+= sub_funcs
;
4793 ITypeInfo_Release(pSubTypeInfo
);
4796 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
4800 *funcs
= implemented_funcs
+ This
->TypeAttr
.cFuncs
;
4804 if (index
< implemented_funcs
)
4805 return E_INVALIDARG
;
4806 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
4810 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
4812 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
4815 switch (pTypeDesc
->vt
)
4817 case VT_USERDEFINED
:
4818 pTypeDesc
->u
.hreftype
+= hrefoffset
;
4822 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
4825 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
4833 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
4836 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
4837 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
4838 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
4841 /* ITypeInfo::GetFuncDesc
4843 * Retrieves the FUNCDESC structure that contains information about a
4844 * specified function.
4847 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
4848 LPFUNCDESC
*ppFuncDesc
)
4850 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4851 const FUNCDESC
*internal_funcdesc
;
4853 UINT hrefoffset
= 0;
4855 TRACE("(%p) index %d\n", This
, index
);
4857 if (This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
4858 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
4859 &internal_funcdesc
, NULL
,
4862 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
4863 &internal_funcdesc
);
4866 WARN("description for function %d not found\n", index
);
4870 hr
= TLB_AllocAndInitFuncDesc(
4873 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
4875 if ((This
->TypeAttr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
4876 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
4878 TRACE("-- 0x%08x\n", hr
);
4882 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
4886 SIZE_T size
= sizeof(*src
);
4889 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
4890 if (src
->varkind
== VAR_CONST
)
4891 size
+= sizeof(VARIANT
);
4892 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
4894 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
4895 if (!dest
) return E_OUTOFMEMORY
;
4898 buffer
= (char *)(dest
+ 1);
4899 if (src
->lpstrSchema
)
4902 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
4903 len
= strlenW(src
->lpstrSchema
);
4904 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
4905 buffer
+= (len
+ 1) * sizeof(WCHAR
);
4908 if (src
->varkind
== VAR_CONST
)
4912 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
4913 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
4914 buffer
+= sizeof(VARIANT
);
4915 VariantInit(dest
->u
.lpvarValue
);
4916 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
4919 SysFreeString((BSTR
)dest_ptr
);
4923 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
4926 if (src
->varkind
== VAR_CONST
)
4927 VariantClear(dest
->u
.lpvarValue
);
4928 SysFreeString((BSTR
)dest
);
4935 /* ITypeInfo::GetVarDesc
4937 * Retrieves a VARDESC structure that describes the specified variable.
4940 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
4941 LPVARDESC
*ppVarDesc
)
4943 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4945 const TLBVarDesc
*pVDesc
;
4947 TRACE("(%p) index %d\n", This
, index
);
4949 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
4953 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
4955 return E_INVALIDARG
;
4958 /* ITypeInfo_GetNames
4960 * Retrieves the variable with the specified member ID (or the name of the
4961 * property or method and its parameters) that correspond to the specified
4964 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
4965 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
4967 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4968 const TLBFuncDesc
*pFDesc
;
4969 const TLBVarDesc
*pVDesc
;
4971 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
4972 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
4975 /* function found, now return function and parameter names */
4976 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
4979 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
4981 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
4987 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
4990 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
4995 if(This
->impltypelist
&&
4996 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4997 /* recursive search */
5000 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
5002 if(SUCCEEDED(result
))
5004 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
5005 ITypeInfo_Release(pTInfo
);
5008 WARN("Could not search inherited interface!\n");
5012 WARN("no names found\n");
5015 return TYPE_E_ELEMENTNOTFOUND
;
5022 /* ITypeInfo::GetRefTypeOfImplType
5024 * If a type description describes a COM class, it retrieves the type
5025 * description of the implemented interface types. For an interface,
5026 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5030 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
5035 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5038 const TLBImplType
*pImpl
= This
->impltypelist
;
5040 TRACE("(%p) index %d\n", This
, index
);
5041 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
5045 /* only valid on dual interfaces;
5046 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5048 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
5050 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
5051 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
5057 hr
= TYPE_E_ELEMENTNOTFOUND
;
5060 else if(index
== 0 && This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5062 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5063 *pRefType
= This
->pTypeLib
->dispatch_href
;
5067 /* get element n from linked list */
5068 for(i
=0; pImpl
&& i
<index
; i
++)
5070 pImpl
= pImpl
->next
;
5074 *pRefType
= pImpl
->hRef
;
5076 hr
= TYPE_E_ELEMENTNOTFOUND
;
5082 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
5084 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
5090 /* ITypeInfo::GetImplTypeFlags
5092 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5093 * or base interface in a type description.
5095 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
5096 UINT index
, INT
*pImplTypeFlags
)
5098 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5102 TRACE("(%p) index %d\n", This
, index
);
5103 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
5104 i
++, pImpl
=pImpl
->next
)
5106 if(i
==index
&& pImpl
){
5107 *pImplTypeFlags
=pImpl
->implflags
;
5111 return TYPE_E_ELEMENTNOTFOUND
;
5115 * Maps between member names and member IDs, and parameter names and
5118 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
5119 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
5121 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5122 const TLBFuncDesc
*pFDesc
;
5123 const TLBVarDesc
*pVDesc
;
5127 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
5130 /* init out parameters in case of failure */
5131 for (i
= 0; i
< cNames
; i
++)
5132 pMemId
[i
] = MEMBERID_NIL
;
5134 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
5136 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
5137 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
5138 for(i
=1; i
< cNames
; i
++){
5139 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
5140 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
5142 if( j
<pFDesc
->funcdesc
.cParams
)
5145 ret
=DISP_E_UNKNOWNNAME
;
5147 TRACE("-- 0x%08x\n", ret
);
5151 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
5152 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
5153 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
5157 /* not found, see if it can be found in an inherited interface */
5158 if(This
->impltypelist
) {
5159 /* recursive search */
5161 ret
=ITypeInfo_GetRefTypeInfo(iface
,
5162 This
->impltypelist
->hRef
, &pTInfo
);
5164 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
5165 ITypeInfo_Release(pTInfo
);
5168 WARN("Could not search inherited interface!\n");
5170 WARN("no names found\n");
5171 return DISP_E_UNKNOWNNAME
;
5174 /* ITypeInfo::Invoke
5176 * Invokes a method, or accesses a property of an object, that implements the
5177 * interface described by the type description.
5180 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
5183 if (TRACE_ON(ole
)) {
5185 TRACE("Calling %p(",func
);
5186 for (i
=0;i
<nrargs
;i
++) TRACE("%08x,",args
[i
]);
5198 res
= func(args
[0]);
5201 res
= func(args
[0],args
[1]);
5204 res
= func(args
[0],args
[1],args
[2]);
5207 res
= func(args
[0],args
[1],args
[2],args
[3]);
5210 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
5213 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
5216 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
5219 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
5222 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
5225 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9]);
5228 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10]);
5231 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]);
5234 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]);
5237 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]);
5240 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]);
5243 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]);
5246 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]);
5249 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]);
5252 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]);
5255 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]);
5258 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]);
5261 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]);
5264 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]);
5267 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]);
5270 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]);
5273 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]);
5276 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]);
5279 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]);
5282 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]);
5285 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]);
5288 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
5294 FIXME("unsupported calling convention %d\n",callconv
);
5298 TRACE("returns %08x\n",res
);
5302 extern int _argsize(DWORD vt
);
5304 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5307 ITypeInfo
*tinfo2
= NULL
;
5308 TYPEATTR
*tattr
= NULL
;
5310 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
5313 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5315 tdesc
->u
.hreftype
, hr
);
5318 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
5321 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
5322 ITypeInfo_Release(tinfo2
);
5326 switch (tattr
->typekind
)
5333 tdesc
= &tattr
->tdescAlias
;
5334 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
5337 case TKIND_INTERFACE
:
5338 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
5344 case TKIND_DISPATCH
:
5353 FIXME("TKIND_RECORD unhandled.\n");
5358 FIXME("TKIND_UNION unhandled.\n");
5363 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
5367 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
5368 ITypeInfo_Release(tinfo2
);
5372 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5376 /* enforce only one level of pointer indirection */
5377 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
5379 tdesc
= tdesc
->u
.lptdesc
;
5381 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5382 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5383 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5384 if ((tdesc
->vt
== VT_USERDEFINED
) ||
5385 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
5387 VARTYPE vt_userdefined
= 0;
5388 const TYPEDESC
*tdesc_userdefined
= tdesc
;
5389 if (tdesc
->vt
== VT_PTR
)
5391 vt_userdefined
= VT_BYREF
;
5392 tdesc_userdefined
= tdesc
->u
.lptdesc
;
5394 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
5396 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
5397 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
5399 *vt
|= vt_userdefined
;
5411 case VT_USERDEFINED
:
5412 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
5419 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
5420 hr
= DISP_E_BADVARTYPE
;
5424 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
5433 /***********************************************************************
5434 * DispCallFunc (OLEAUT32.@)
5436 * Invokes a function of the specifed calling convention, passing the
5437 * specified arguments and returns the result.
5440 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5441 * oVft [I] The offset in the vtable. See notes.
5442 * cc [I] Calling convention of the function to call.
5443 * vtReturn [I] The return type of the function.
5444 * cActuals [I] Number of parameters.
5445 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5446 * prgpvarg [I] The arguments to pass.
5447 * pvargResult [O] The return value of the function. Can be NULL.
5451 * Failure: HRESULT code.
5454 * The HRESULT return value of this function is not affected by the return
5455 * value of the user supplied function, which is returned in pvargResult.
5457 * If pvInstance is NULL then a non-object function is to be called and oVft
5458 * is the address of the function to call.
5460 * The cc parameter can be one of the following values:
5473 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
5474 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
5476 int i
, argsize
, argspos
;
5480 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5481 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
5482 pvargResult
, V_VT(pvargResult
));
5486 argsize
++; /* for This pointer */
5488 for (i
=0;i
<cActuals
;i
++)
5490 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
5491 dump_Variant(prgpvarg
[i
]);
5492 argsize
+= _argsize(prgvt
[i
]);
5494 args
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
5499 args
[0] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
5503 for (i
=0;i
<cActuals
;i
++)
5505 VARIANT
*arg
= prgpvarg
[i
];
5506 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
5507 if (prgvt
[i
] == VT_VARIANT
)
5508 memcpy(&args
[argspos
], arg
, _argsize(prgvt
[i
]) * sizeof(DWORD
));
5510 memcpy(&args
[argspos
], &V_NONE(arg
), _argsize(prgvt
[i
]) * sizeof(DWORD
));
5511 argspos
+= _argsize(prgvt
[i
]);
5516 FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
5517 hres
= _invoke(vtable
[oVft
/sizeof(void *)], cc
, argsize
, args
);
5520 /* if we aren't invoking an object then the function pointer is stored
5522 hres
= _invoke((FARPROC
)oVft
, cc
, argsize
, args
);
5524 if (pvargResult
&& (vtReturn
!= VT_EMPTY
))
5526 TRACE("Method returned 0x%08x\n",hres
);
5527 V_VT(pvargResult
) = vtReturn
;
5528 V_UI4(pvargResult
) = hres
;
5531 HeapFree(GetProcessHeap(),0,args
);
5535 #define INVBUF_ELEMENT_SIZE \
5536 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5537 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5538 ((VARIANTARG *)(buffer))
5539 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5540 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5541 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5542 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5543 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5544 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5546 static HRESULT WINAPI
ITypeInfo_fnInvoke(
5551 DISPPARAMS
*pDispParams
,
5552 VARIANT
*pVarResult
,
5553 EXCEPINFO
*pExcepInfo
,
5556 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5558 unsigned int var_index
;
5561 const TLBFuncDesc
*pFuncInfo
;
5563 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5564 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
5569 ERR("NULL pDispParams not allowed\n");
5570 return E_INVALIDARG
;
5573 dump_DispParms(pDispParams
);
5575 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
5577 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5578 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
5579 return E_INVALIDARG
;
5582 /* we do this instead of using GetFuncDesc since it will return a fake
5583 * FUNCDESC for dispinterfaces and we want the real function description */
5584 for (pFuncInfo
= This
->funclist
; pFuncInfo
; pFuncInfo
=pFuncInfo
->next
)
5585 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
5586 (wFlags
& pFuncInfo
->funcdesc
.invkind
))
5590 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
5594 TRACE("invoking:\n");
5595 dump_TLBFuncDescOne(pFuncInfo
);
5598 switch (func_desc
->funckind
) {
5599 case FUNC_PUREVIRTUAL
:
5600 case FUNC_VIRTUAL
: {
5601 void *buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
5603 VARIANT retval
; /* pointer for storing byref retvals in */
5604 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
5605 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
5606 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
5607 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
5608 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
5612 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
5614 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
5616 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5617 hres
= DISP_E_PARAMNOTFOUND
;
5620 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5622 rgdispidNamedArgs
++;
5625 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
5627 ERR("functions with the vararg attribute do not support named arguments\n");
5628 hres
= DISP_E_NONAMEDARGS
;
5632 for (i
= 0; i
< func_desc
->cParams
; i
++)
5634 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
5635 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
5640 TRACE("changing args\n");
5641 for (i
= 0; i
< func_desc
->cParams
; i
++)
5643 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
5644 VARIANTARG
*src_arg
;
5650 for (j
= 0; j
< cNamedArgs
; j
++)
5651 if (rgdispidNamedArgs
[j
] == i
)
5653 src_arg
= &pDispParams
->rgvarg
[j
];
5658 src_arg
= i
< pDispParams
->cArgs
? &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
] : NULL
;
5660 if (wParamFlags
& PARAMFLAG_FRETVAL
)
5662 /* under most conditions the caller is not allowed to
5663 * pass in a dispparam arg in the index of what would be
5664 * the retval parameter. however, there is an exception
5665 * where the extra parameter is used in an extra
5666 * IDispatch::Invoke below */
5667 if ((i
< pDispParams
->cArgs
) &&
5668 ((func_desc
->cParams
!= 1) || !pVarResult
||
5669 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
5671 hres
= DISP_E_BADPARAMCOUNT
;
5675 /* note: this check is placed so that if the caller passes
5676 * in a VARIANTARG for the retval we just ignore it, like
5678 if (i
== func_desc
->cParams
- 1)
5681 arg
= prgpvarg
[i
] = &rgvarg
[i
];
5682 memset(arg
, 0, sizeof(*arg
));
5683 V_VT(arg
) = rgvt
[i
];
5684 memset(&retval
, 0, sizeof(retval
));
5685 V_BYREF(arg
) = &retval
;
5689 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
5690 hres
= E_UNEXPECTED
;
5696 dump_Variant(src_arg
);
5698 if (rgvt
[i
] == VT_VARIANT
)
5699 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
5700 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
5702 if (rgvt
[i
] == V_VT(src_arg
))
5703 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
5706 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
5707 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
5708 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
5710 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5712 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
5715 SAFEARRAYBOUND bound
;
5719 bound
.cElements
= pDispParams
->cArgs
-i
;
5720 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
5722 ERR("SafeArrayCreate failed\n");
5725 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
5728 ERR("SafeArrayAccessData failed with %x\n", hres
);
5731 for (j
= 0; j
< bound
.cElements
; j
++)
5732 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
5733 hres
= SafeArrayUnaccessData(a
);
5736 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
5739 V_ARRAY(&rgvarg
[i
]) = a
;
5740 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5742 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
5744 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
5745 V_VT(&missing_arg
[i
]) = V_VT(src_arg
);
5746 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
5747 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
5748 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5750 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
5752 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
5753 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5757 /* FIXME: this doesn't work for VT_BYREF arguments if
5758 * they are not the same type as in the paramdesc */
5759 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
5760 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
5761 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5766 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
5767 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
5768 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
5771 prgpvarg
[i
] = &rgvarg
[i
];
5773 else if (wParamFlags
& PARAMFLAG_FOPT
)
5776 arg
= prgpvarg
[i
] = &rgvarg
[i
];
5777 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5779 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
5785 VARIANTARG
*missing_arg
;
5786 /* if the function wants a pointer to a variant then
5787 * set that up, otherwise just pass the VT_ERROR in
5788 * the argument by value */
5789 if (rgvt
[i
] & VT_BYREF
)
5791 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
5792 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
5793 V_VARIANTREF(arg
) = missing_arg
;
5797 V_VT(missing_arg
) = VT_ERROR
;
5798 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
5803 hres
= DISP_E_BADPARAMCOUNT
;
5807 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
5809 /* VT_VOID is a special case for return types, so it is not
5810 * handled in the general function */
5811 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
5812 V_VT(&varresult
) = VT_EMPTY
;
5815 V_VT(&varresult
) = 0;
5816 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
5817 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
5820 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
, func_desc
->callconv
,
5821 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
5822 prgpvarg
, &varresult
);
5824 for (i
= 0; i
< func_desc
->cParams
; i
++)
5826 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
5827 if (wParamFlags
& PARAMFLAG_FRETVAL
)
5831 TRACE("[retval] value: ");
5832 dump_Variant(prgpvarg
[i
]);
5837 VariantInit(pVarResult
);
5838 /* deref return value */
5839 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
5842 /* free data stored in varresult. Note that
5843 * VariantClear doesn't do what we want because we are
5844 * working with byref types. */
5845 /* FIXME: clear safearrays, bstrs, records and
5846 * variants here too */
5847 if ((V_VT(prgpvarg
[i
]) == (VT_UNKNOWN
| VT_BYREF
)) ||
5848 (V_VT(prgpvarg
[i
]) == (VT_DISPATCH
| VT_BYREF
)))
5850 if(*V_UNKNOWNREF(prgpvarg
[i
]))
5851 IUnknown_Release(*V_UNKNOWNREF(prgpvarg
[i
]));
5855 else if (i
< pDispParams
->cArgs
)
5857 if (wParamFlags
& PARAMFLAG_FOUT
)
5859 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
];
5861 if ((rgvt
[i
] == VT_BYREF
) && (V_VT(arg
) != VT_BYREF
))
5862 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
5866 ERR("failed to convert param %d to vt %d\n", i
,
5867 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
]));
5871 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
5872 func_desc
->cParamsOpt
< 0 &&
5873 i
== func_desc
->cParams
-1)
5875 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
5878 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
5881 ERR("SafeArrayGetUBound failed with %x\n", hres
);
5884 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
5887 ERR("SafeArrayAccessData failed with %x\n", hres
);
5890 for (j
= 0; j
<= ubound
; j
++)
5891 VariantClear(&v
[j
]);
5892 hres
= SafeArrayUnaccessData(a
);
5895 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
5899 VariantClear(&rgvarg
[i
]);
5901 else if (wParamFlags
& PARAMFLAG_FOPT
)
5903 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5904 VariantClear(&rgvarg
[i
]);
5908 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
5910 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
5911 hres
= DISP_E_EXCEPTION
;
5914 IErrorInfo
*pErrorInfo
;
5915 pExcepInfo
->scode
= V_ERROR(&varresult
);
5916 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
5918 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
5919 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
5920 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
5921 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
5923 IErrorInfo_Release(pErrorInfo
);
5927 if (V_VT(&varresult
) != VT_ERROR
)
5929 TRACE("varresult value: ");
5930 dump_Variant(&varresult
);
5934 VariantClear(pVarResult
);
5935 *pVarResult
= varresult
;
5938 VariantClear(&varresult
);
5941 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
5942 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
5943 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
5944 (pDispParams
->cArgs
!= 0))
5946 if (V_VT(pVarResult
) == VT_DISPATCH
)
5948 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
5949 /* Note: not VariantClear; we still need the dispatch
5950 * pointer to be valid */
5951 VariantInit(pVarResult
);
5952 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
5953 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
5954 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
5955 IDispatch_Release(pDispatch
);
5959 VariantClear(pVarResult
);
5960 hres
= DISP_E_NOTACOLLECTION
;
5965 HeapFree(GetProcessHeap(), 0, buffer
);
5968 case FUNC_DISPATCH
: {
5971 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
5972 if (SUCCEEDED(hres
)) {
5973 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5974 hres
= IDispatch_Invoke(
5975 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
5976 pVarResult
,pExcepInfo
,pArgErr
5979 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
5980 IDispatch_Release(disp
);
5982 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5986 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
5991 TRACE("-- 0x%08x\n", hres
);
5994 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
5997 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
5998 if(FAILED(hres
)) return hres
;
6000 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6001 dump_VARDESC(var_desc
);
6002 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
6006 /* not found, look for it in inherited interfaces */
6007 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
6008 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
6009 if(This
->impltypelist
) {
6010 /* recursive search */
6012 hres
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pTInfo
);
6013 if(SUCCEEDED(hres
)){
6014 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
6015 ITypeInfo_Release(pTInfo
);
6018 WARN("Could not search inherited interface!\n");
6021 ERR("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
6022 return DISP_E_MEMBERNOTFOUND
;
6025 /* ITypeInfo::GetDocumentation
6027 * Retrieves the documentation string, the complete Help file name and path,
6028 * and the context ID for the Help topic for a specified type description.
6030 * (Can be tested by the Visual Basic Editor in Word for instance.)
6032 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
6033 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
6034 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
6036 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6037 const TLBFuncDesc
*pFDesc
;
6038 const TLBVarDesc
*pVDesc
;
6039 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6040 " HelpContext(%p) HelpFile(%p)\n",
6041 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6042 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
6044 *pBstrName
=SysAllocString(This
->Name
);
6046 *pBstrDocString
=SysAllocString(This
->DocString
);
6048 *pdwHelpContext
=This
->dwHelpContext
;
6050 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
6052 }else {/* for a member */
6053 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6054 if(pFDesc
->funcdesc
.memid
==memid
){
6056 *pBstrName
= SysAllocString(pFDesc
->Name
);
6058 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
6060 *pdwHelpContext
=pFDesc
->helpcontext
;
6063 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
6064 if(pVDesc
->vardesc
.memid
==memid
){
6066 *pBstrName
= SysAllocString(pVDesc
->Name
);
6068 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
6070 *pdwHelpContext
=pVDesc
->HelpContext
;
6075 if(This
->impltypelist
&&
6076 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
6077 /* recursive search */
6080 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
6082 if(SUCCEEDED(result
)) {
6083 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
6084 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6085 ITypeInfo_Release(pTInfo
);
6088 WARN("Could not search inherited interface!\n");
6091 WARN("member %d not found\n", memid
);
6092 return TYPE_E_ELEMENTNOTFOUND
;
6095 /* ITypeInfo::GetDllEntry
6097 * Retrieves a description or specification of an entry point for a function
6100 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
6101 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
6104 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6105 const TLBFuncDesc
*pFDesc
;
6107 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
6109 if (pBstrDllName
) *pBstrDllName
= NULL
;
6110 if (pBstrName
) *pBstrName
= NULL
;
6111 if (pwOrdinal
) *pwOrdinal
= 0;
6113 if (This
->TypeAttr
.typekind
!= TKIND_MODULE
)
6114 return TYPE_E_BADMODULEKIND
;
6116 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6117 if(pFDesc
->funcdesc
.memid
==memid
){
6118 dump_TypeInfo(This
);
6120 dump_TLBFuncDescOne(pFDesc
);
6123 *pBstrDllName
= SysAllocString(This
->DllName
);
6125 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
6127 *pBstrName
= SysAllocString(pFDesc
->Entry
);
6135 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
6138 return TYPE_E_ELEMENTNOTFOUND
;
6141 /* internal function to make the inherited interfaces' methods appear
6142 * part of the interface */
6143 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
6144 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
6146 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6149 TRACE("%p, 0x%x\n", iface
, *hRefType
);
6151 if (This
->impltypelist
&& (*hRefType
& DISPATCH_HREF_MASK
))
6153 ITypeInfo
*pSubTypeInfo
;
6155 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pSubTypeInfo
);
6159 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
6161 ITypeInfo_Release(pSubTypeInfo
);
6165 *hRefType
-= DISPATCH_HREF_OFFSET
;
6167 if (!(*hRefType
& DISPATCH_HREF_MASK
))
6168 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
6173 /* ITypeInfo::GetRefTypeInfo
6175 * If a type description references other type descriptions, it retrieves
6176 * the referenced type descriptions.
6178 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
6181 ITypeInfo
**ppTInfo
)
6183 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6184 HRESULT result
= E_FAIL
;
6186 if ((This
->hreftype
!= -1) && (This
->hreftype
== hRefType
))
6188 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6189 ITypeInfo_AddRef(*ppTInfo
);
6192 else if (hRefType
== -1 &&
6193 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
6194 (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
6196 /* when we meet a DUAL dispinterface, we must create the interface
6199 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
6202 /* the interface version contains the same information as the dispinterface
6203 * copy the contents of the structs.
6205 *pTypeInfoImpl
= *This
;
6206 pTypeInfoImpl
->ref
= 0;
6208 /* change the type to interface */
6209 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
6211 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
6213 /* we use data structures from This, so we need to keep a reference
6214 * to it to stop it being destroyed and signal to the new instance to
6215 * not free its data structures when it is destroyed */
6216 pTypeInfoImpl
->no_free_data
= TRUE
;
6217 pTypeInfoImpl
->next
= This
;
6218 ITypeInfo_AddRef((ITypeInfo
*) This
);
6220 ITypeInfo_AddRef(*ppTInfo
);
6224 } else if ((hRefType
!= -1) && (hRefType
& DISPATCH_HREF_MASK
) &&
6225 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
6226 (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
6228 HREFTYPE href_dispatch
= hRefType
;
6229 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
6231 TLBRefType
*ref_type
;
6232 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
6234 if(ref_type
->reference
== hRefType
)
6237 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
6239 FIXME("Can't find pRefType for ref %x\n", hRefType
);
6242 if(hRefType
!= -1) {
6243 ITypeLib
*pTLib
= NULL
;
6245 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
6247 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
6249 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
6250 TRACE("typeinfo in imported typelib that is already loaded\n");
6251 pTLib
= (ITypeLib
*)ref_type
->pImpTLInfo
->pImpTypeLib
;
6252 ITypeLib2_AddRef(pTLib
);
6255 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6256 result
= LoadRegTypeLib( &ref_type
->pImpTLInfo
->guid
,
6257 ref_type
->pImpTLInfo
->wVersionMajor
,
6258 ref_type
->pImpTLInfo
->wVersionMinor
,
6259 ref_type
->pImpTLInfo
->lcid
,
6262 if(!SUCCEEDED(result
)) {
6263 BSTR libnam
=SysAllocString(ref_type
->pImpTLInfo
->name
);
6264 result
=LoadTypeLib(libnam
, &pTLib
);
6265 SysFreeString(libnam
);
6267 if(SUCCEEDED(result
)) {
6268 ref_type
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
6269 ITypeLib2_AddRef(pTLib
);
6273 if(SUCCEEDED(result
)) {
6274 if(ref_type
->index
== TLB_REF_USE_GUID
)
6275 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
6279 result
= ITypeLib2_GetTypeInfo(pTLib
, ref_type
->index
,
6283 ITypeLib2_Release(pTLib
);
6288 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
6289 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
6293 /* ITypeInfo::AddressOfMember
6295 * Retrieves the addresses of static functions or variables, such as those
6298 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
6299 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
6301 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6307 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
6309 hr
= ITypeInfo_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
6313 module
= LoadLibraryW(dll
);
6316 ERR("couldn't load %s\n", debugstr_w(dll
));
6318 if (entry
) SysFreeString(entry
);
6319 return STG_E_FILENOTFOUND
;
6321 /* FIXME: store library somewhere where we can free it */
6326 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
6327 entryA
= HeapAlloc(GetProcessHeap(), 0, len
);
6328 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
6330 *ppv
= GetProcAddress(module
, entryA
);
6332 ERR("function not found %s\n", debugstr_a(entryA
));
6334 HeapFree(GetProcessHeap(), 0, entryA
);
6338 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
6340 ERR("function not found %d\n", ordinal
);
6344 if (entry
) SysFreeString(entry
);
6347 return TYPE_E_DLLFUNCTIONNOTFOUND
;
6352 /* ITypeInfo::CreateInstance
6354 * Creates a new instance of a type that describes a component object class
6357 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
6358 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
6360 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6364 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
6370 WARN("Not able to aggregate\n");
6371 return CLASS_E_NOAGGREGATION
;
6374 hr
= ITypeInfo_GetTypeAttr(iface
, &pTA
);
6375 if(FAILED(hr
)) return hr
;
6377 if(pTA
->typekind
!= TKIND_COCLASS
)
6379 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
6385 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
6388 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
6389 TRACE("GetActiveObject rets %08x\n", hr
);
6392 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
6393 IUnknown_Release(pUnk
);
6398 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
6399 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
6403 ITypeInfo_ReleaseTypeAttr(iface
, pTA
);
6407 /* ITypeInfo::GetMops
6409 * Retrieves marshalling information.
6411 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
6414 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6415 FIXME("(%p) stub!\n", This
);
6419 /* ITypeInfo::GetContainingTypeLib
6421 * Retrieves the containing type library and the index of the type description
6422 * within that type library.
6424 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
6425 ITypeLib
* *ppTLib
, UINT
*pIndex
)
6427 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6429 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6431 *pIndex
=This
->index
;
6432 TRACE("returning pIndex=%d\n", *pIndex
);
6436 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
6437 ITypeLib2_AddRef(*ppTLib
);
6438 TRACE("returning ppTLib=%p\n", *ppTLib
);
6444 /* ITypeInfo::ReleaseTypeAttr
6446 * Releases a TYPEATTR previously returned by GetTypeAttr.
6449 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
6450 TYPEATTR
* pTypeAttr
)
6452 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6453 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
6454 HeapFree(GetProcessHeap(), 0, pTypeAttr
);
6457 /* ITypeInfo::ReleaseFuncDesc
6459 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6461 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
6463 FUNCDESC
*pFuncDesc
)
6465 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6468 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
6470 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6471 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
6472 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
6474 SysFreeString((BSTR
)pFuncDesc
);
6477 /* ITypeInfo::ReleaseVarDesc
6479 * Releases a VARDESC previously returned by GetVarDesc.
6481 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
6484 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6485 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
6487 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
6488 if (pVarDesc
->varkind
== VAR_CONST
)
6489 VariantClear(pVarDesc
->u
.lpvarValue
);
6490 SysFreeString((BSTR
)pVarDesc
);
6493 /* ITypeInfo2::GetTypeKind
6495 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6498 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
6499 TYPEKIND
*pTypeKind
)
6501 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6502 *pTypeKind
=This
->TypeAttr
.typekind
;
6503 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
6507 /* ITypeInfo2::GetTypeFlags
6509 * Returns the type flags without any allocations. This returns a DWORD type
6510 * flag, which expands the type flags without growing the TYPEATTR (type
6514 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
6516 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6517 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
6518 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
6522 /* ITypeInfo2::GetFuncIndexOfMemId
6523 * Binds to a specific member based on a known DISPID, where the member name
6524 * is not known (for example, when binding to a default member).
6527 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
6528 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
6530 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6531 const TLBFuncDesc
*pFuncInfo
;
6535 for(i
= 0, pFuncInfo
= This
->funclist
; pFuncInfo
; i
++, pFuncInfo
=pFuncInfo
->next
)
6536 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
6542 result
= TYPE_E_ELEMENTNOTFOUND
;
6544 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
6545 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
6549 /* TypeInfo2::GetVarIndexOfMemId
6551 * Binds to a specific member based on a known DISPID, where the member name
6552 * is not known (for example, when binding to a default member).
6555 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
6556 MEMBERID memid
, UINT
*pVarIndex
)
6558 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6559 TLBVarDesc
*pVarInfo
;
6562 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
6563 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
6569 result
= TYPE_E_ELEMENTNOTFOUND
;
6571 TRACE("(%p) memid 0x%08x -> %s\n", This
,
6572 memid
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
6576 /* ITypeInfo2::GetCustData
6578 * Gets the custom data
6580 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
6585 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6586 TLBCustData
*pCData
;
6588 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
6589 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6591 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6595 VariantInit( pVarVal
);
6596 VariantCopy( pVarVal
, &pCData
->data
);
6599 return E_INVALIDARG
; /* FIXME: correct? */
6602 /* ITypeInfo2::GetFuncCustData
6604 * Gets the custom data
6606 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
6612 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6613 TLBCustData
*pCData
=NULL
;
6614 TLBFuncDesc
* pFDesc
;
6616 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
6617 pFDesc
=pFDesc
->next
);
6620 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
6621 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6623 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6626 VariantInit( pVarVal
);
6627 VariantCopy( pVarVal
, &pCData
->data
);
6630 return E_INVALIDARG
; /* FIXME: correct? */
6633 /* ITypeInfo2::GetParamCustData
6635 * Gets the custom data
6637 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
6644 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6645 TLBCustData
*pCData
=NULL
;
6646 TLBFuncDesc
* pFDesc
;
6649 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
6651 if(pFDesc
&& indexParam
<pFDesc
->funcdesc
.cParams
)
6652 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
6653 pCData
= pCData
->next
)
6654 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6656 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6660 VariantInit( pVarVal
);
6661 VariantCopy( pVarVal
, &pCData
->data
);
6664 return E_INVALIDARG
; /* FIXME: correct? */
6667 /* ITypeInfo2::GetVarCustData
6669 * Gets the custom data
6671 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
6677 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6678 TLBCustData
*pCData
=NULL
;
6679 TLBVarDesc
* pVDesc
;
6682 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
6686 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
6688 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6692 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6696 VariantInit( pVarVal
);
6697 VariantCopy( pVarVal
, &pCData
->data
);
6700 return E_INVALIDARG
; /* FIXME: correct? */
6703 /* ITypeInfo2::GetImplCustData
6705 * Gets the custom data
6707 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
6713 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6714 TLBCustData
*pCData
=NULL
;
6715 TLBImplType
* pRDesc
;
6718 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
6722 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
6724 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6728 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6732 VariantInit( pVarVal
);
6733 VariantCopy( pVarVal
, &pCData
->data
);
6736 return E_INVALIDARG
; /* FIXME: correct? */
6739 /* ITypeInfo2::GetDocumentation2
6741 * Retrieves the documentation string, the complete Help file name and path,
6742 * the localization context to use, and the context ID for the library Help
6743 * topic in the Help file.
6746 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
6750 BSTR
*pbstrHelpString
,
6751 DWORD
*pdwHelpStringContext
,
6752 BSTR
*pbstrHelpStringDll
)
6754 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6755 const TLBFuncDesc
*pFDesc
;
6756 const TLBVarDesc
*pVDesc
;
6757 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6758 "HelpStringContext(%p) HelpStringDll(%p)\n",
6759 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
6760 pbstrHelpStringDll
);
6761 /* the help string should be obtained from the helpstringdll,
6762 * using the _DLLGetDocumentation function, based on the supplied
6763 * lcid. Nice to do sometime...
6765 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
6767 *pbstrHelpString
=SysAllocString(This
->Name
);
6768 if(pdwHelpStringContext
)
6769 *pdwHelpStringContext
=This
->dwHelpStringContext
;
6770 if(pbstrHelpStringDll
)
6771 *pbstrHelpStringDll
=
6772 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6774 }else {/* for a member */
6775 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6776 if(pFDesc
->funcdesc
.memid
==memid
){
6778 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
6779 if(pdwHelpStringContext
)
6780 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
6781 if(pbstrHelpStringDll
)
6782 *pbstrHelpStringDll
=
6783 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6786 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
6787 if(pVDesc
->vardesc
.memid
==memid
){
6789 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
6790 if(pdwHelpStringContext
)
6791 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
6792 if(pbstrHelpStringDll
)
6793 *pbstrHelpStringDll
=
6794 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6798 return TYPE_E_ELEMENTNOTFOUND
;
6801 /* ITypeInfo2::GetAllCustData
6803 * Gets all custom data items for the Type info.
6806 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
6808 CUSTDATA
*pCustData
)
6810 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6811 TLBCustData
*pCData
;
6814 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
6816 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
6817 if(pCustData
->prgCustData
){
6818 pCustData
->cCustData
=This
->ctCustData
;
6819 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
6820 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6821 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
6824 ERR(" OUT OF MEMORY!\n");
6825 return E_OUTOFMEMORY
;
6830 /* ITypeInfo2::GetAllFuncCustData
6832 * Gets all custom data items for the specified Function
6835 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
6838 CUSTDATA
*pCustData
)
6840 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6841 TLBCustData
*pCData
;
6842 TLBFuncDesc
* pFDesc
;
6844 TRACE("(%p) index %d\n", This
, index
);
6845 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
6846 pFDesc
=pFDesc
->next
)
6849 pCustData
->prgCustData
=
6850 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
6851 if(pCustData
->prgCustData
){
6852 pCustData
->cCustData
=pFDesc
->ctCustData
;
6853 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
6854 pCData
= pCData
->next
){
6855 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6856 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6860 ERR(" OUT OF MEMORY!\n");
6861 return E_OUTOFMEMORY
;
6865 return TYPE_E_ELEMENTNOTFOUND
;
6868 /* ITypeInfo2::GetAllParamCustData
6870 * Gets all custom data items for the Functions
6873 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
6874 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
6876 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6877 TLBCustData
*pCData
=NULL
;
6878 TLBFuncDesc
* pFDesc
;
6880 TRACE("(%p) index %d\n", This
, indexFunc
);
6881 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
6882 pFDesc
=pFDesc
->next
)
6884 if(pFDesc
&& indexParam
<pFDesc
->funcdesc
.cParams
){
6885 pCustData
->prgCustData
=
6886 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
6887 sizeof(CUSTDATAITEM
));
6888 if(pCustData
->prgCustData
){
6889 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
6890 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
6891 pCData
; i
++, pCData
= pCData
->next
){
6892 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6893 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6897 ERR(" OUT OF MEMORY!\n");
6898 return E_OUTOFMEMORY
;
6902 return TYPE_E_ELEMENTNOTFOUND
;
6905 /* ITypeInfo2::GetAllVarCustData
6907 * Gets all custom data items for the specified Variable
6910 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
6911 UINT index
, CUSTDATA
*pCustData
)
6913 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6914 TLBCustData
*pCData
;
6915 TLBVarDesc
* pVDesc
;
6917 TRACE("(%p) index %d\n", This
, index
);
6918 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
6919 pVDesc
=pVDesc
->next
)
6922 pCustData
->prgCustData
=
6923 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
6924 if(pCustData
->prgCustData
){
6925 pCustData
->cCustData
=pVDesc
->ctCustData
;
6926 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
6927 pCData
= pCData
->next
){
6928 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6929 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6933 ERR(" OUT OF MEMORY!\n");
6934 return E_OUTOFMEMORY
;
6938 return TYPE_E_ELEMENTNOTFOUND
;
6941 /* ITypeInfo2::GetAllImplCustData
6943 * Gets all custom data items for the specified implementation type
6946 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
6949 CUSTDATA
*pCustData
)
6951 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6952 TLBCustData
*pCData
;
6953 TLBImplType
* pRDesc
;
6955 TRACE("(%p) index %d\n", This
, index
);
6956 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
6957 pRDesc
=pRDesc
->next
)
6960 pCustData
->prgCustData
=
6961 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
6962 if(pCustData
->prgCustData
){
6963 pCustData
->cCustData
=pRDesc
->ctCustData
;
6964 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
6965 pCData
= pCData
->next
){
6966 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6967 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6971 ERR(" OUT OF MEMORY!\n");
6972 return E_OUTOFMEMORY
;
6976 return TYPE_E_ELEMENTNOTFOUND
;
6979 static const ITypeInfo2Vtbl tinfvt
=
6982 ITypeInfo_fnQueryInterface
,
6984 ITypeInfo_fnRelease
,
6986 ITypeInfo_fnGetTypeAttr
,
6987 ITypeInfo_fnGetTypeComp
,
6988 ITypeInfo_fnGetFuncDesc
,
6989 ITypeInfo_fnGetVarDesc
,
6990 ITypeInfo_fnGetNames
,
6991 ITypeInfo_fnGetRefTypeOfImplType
,
6992 ITypeInfo_fnGetImplTypeFlags
,
6993 ITypeInfo_fnGetIDsOfNames
,
6995 ITypeInfo_fnGetDocumentation
,
6996 ITypeInfo_fnGetDllEntry
,
6997 ITypeInfo_fnGetRefTypeInfo
,
6998 ITypeInfo_fnAddressOfMember
,
6999 ITypeInfo_fnCreateInstance
,
7000 ITypeInfo_fnGetMops
,
7001 ITypeInfo_fnGetContainingTypeLib
,
7002 ITypeInfo_fnReleaseTypeAttr
,
7003 ITypeInfo_fnReleaseFuncDesc
,
7004 ITypeInfo_fnReleaseVarDesc
,
7006 ITypeInfo2_fnGetTypeKind
,
7007 ITypeInfo2_fnGetTypeFlags
,
7008 ITypeInfo2_fnGetFuncIndexOfMemId
,
7009 ITypeInfo2_fnGetVarIndexOfMemId
,
7010 ITypeInfo2_fnGetCustData
,
7011 ITypeInfo2_fnGetFuncCustData
,
7012 ITypeInfo2_fnGetParamCustData
,
7013 ITypeInfo2_fnGetVarCustData
,
7014 ITypeInfo2_fnGetImplTypeCustData
,
7015 ITypeInfo2_fnGetDocumentation2
,
7016 ITypeInfo2_fnGetAllCustData
,
7017 ITypeInfo2_fnGetAllFuncCustData
,
7018 ITypeInfo2_fnGetAllParamCustData
,
7019 ITypeInfo2_fnGetAllVarCustData
,
7020 ITypeInfo2_fnGetAllImplTypeCustData
,
7023 /******************************************************************************
7024 * CreateDispTypeInfo [OLEAUT32.31]
7026 * Build type information for an object so it can be called through an
7027 * IDispatch interface.
7030 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7031 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7034 * This call allows an objects methods to be accessed through IDispatch, by
7035 * building an ITypeInfo object that IDispatch can use to call through.
7037 HRESULT WINAPI
CreateDispTypeInfo(
7038 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
7039 LCID lcid
, /* [I] Locale Id */
7040 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
7042 ITypeInfoImpl
*pTIClass
, *pTIIface
;
7043 ITypeLibImpl
*pTypeLibImpl
;
7045 TLBFuncDesc
**ppFuncDesc
;
7049 pTypeLibImpl
= TypeLibImpl_Constructor();
7050 if (!pTypeLibImpl
) return E_FAIL
;
7052 pTIIface
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
7053 pTIIface
->pTypeLib
= pTypeLibImpl
;
7054 pTIIface
->index
= 0;
7055 pTIIface
->Name
= NULL
;
7056 pTIIface
->dwHelpContext
= -1;
7057 memset(&pTIIface
->TypeAttr
.guid
, 0, sizeof(GUID
));
7058 pTIIface
->TypeAttr
.lcid
= lcid
;
7059 pTIIface
->TypeAttr
.typekind
= TKIND_INTERFACE
;
7060 pTIIface
->TypeAttr
.wMajorVerNum
= 0;
7061 pTIIface
->TypeAttr
.wMinorVerNum
= 0;
7062 pTIIface
->TypeAttr
.cbAlignment
= 2;
7063 pTIIface
->TypeAttr
.cbSizeInstance
= -1;
7064 pTIIface
->TypeAttr
.cbSizeVft
= -1;
7065 pTIIface
->TypeAttr
.cFuncs
= 0;
7066 pTIIface
->TypeAttr
.cImplTypes
= 0;
7067 pTIIface
->TypeAttr
.cVars
= 0;
7068 pTIIface
->TypeAttr
.wTypeFlags
= 0;
7070 ppFuncDesc
= &pTIIface
->funclist
;
7071 for(func
= 0; func
< pidata
->cMembers
; func
++) {
7072 METHODDATA
*md
= pidata
->pmethdata
+ func
;
7073 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
7074 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
7075 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
7076 (*ppFuncDesc
)->funcdesc
.lprgscode
= NULL
;
7077 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_VIRTUAL
;
7078 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
7079 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
7080 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
7081 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
7082 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
<< 2;
7083 (*ppFuncDesc
)->funcdesc
.cScodes
= 0;
7084 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0;
7085 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
7086 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
7087 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
7088 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
7089 md
->cArgs
* sizeof(ELEMDESC
));
7090 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
7091 md
->cArgs
* sizeof(TLBParDesc
));
7092 for(param
= 0; param
< md
->cArgs
; param
++) {
7093 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
7094 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
7096 (*ppFuncDesc
)->helpcontext
= 0;
7097 (*ppFuncDesc
)->HelpStringContext
= 0;
7098 (*ppFuncDesc
)->HelpString
= NULL
;
7099 (*ppFuncDesc
)->Entry
= NULL
;
7100 (*ppFuncDesc
)->ctCustData
= 0;
7101 (*ppFuncDesc
)->pCustData
= NULL
;
7102 (*ppFuncDesc
)->next
= NULL
;
7103 pTIIface
->TypeAttr
.cFuncs
++;
7104 ppFuncDesc
= &(*ppFuncDesc
)->next
;
7107 dump_TypeInfo(pTIIface
);
7109 pTypeLibImpl
->pTypeInfo
= pTIIface
;
7110 pTypeLibImpl
->TypeInfoCount
++;
7112 pTIClass
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
7113 pTIClass
->pTypeLib
= pTypeLibImpl
;
7114 pTIClass
->index
= 1;
7115 pTIClass
->Name
= NULL
;
7116 pTIClass
->dwHelpContext
= -1;
7117 memset(&pTIClass
->TypeAttr
.guid
, 0, sizeof(GUID
));
7118 pTIClass
->TypeAttr
.lcid
= lcid
;
7119 pTIClass
->TypeAttr
.typekind
= TKIND_COCLASS
;
7120 pTIClass
->TypeAttr
.wMajorVerNum
= 0;
7121 pTIClass
->TypeAttr
.wMinorVerNum
= 0;
7122 pTIClass
->TypeAttr
.cbAlignment
= 2;
7123 pTIClass
->TypeAttr
.cbSizeInstance
= -1;
7124 pTIClass
->TypeAttr
.cbSizeVft
= -1;
7125 pTIClass
->TypeAttr
.cFuncs
= 0;
7126 pTIClass
->TypeAttr
.cImplTypes
= 1;
7127 pTIClass
->TypeAttr
.cVars
= 0;
7128 pTIClass
->TypeAttr
.wTypeFlags
= 0;
7130 pTIClass
->impltypelist
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pTIClass
->impltypelist
));
7131 pTIClass
->impltypelist
->hRef
= 0;
7133 ref
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref
));
7136 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
7137 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
7139 dump_TypeInfo(pTIClass
);
7141 pTIIface
->next
= pTIClass
;
7142 pTypeLibImpl
->TypeInfoCount
++;
7144 *pptinfo
= (ITypeInfo
*)pTIClass
;
7146 ITypeInfo_AddRef(*pptinfo
);
7147 ITypeLib_Release((ITypeLib
*)&pTypeLibImpl
->lpVtbl
);
7153 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
7155 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7157 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
7160 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
7162 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7164 return ITypeInfo_AddRef((ITypeInfo
*)This
);
7167 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
7169 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7171 return ITypeInfo_Release((ITypeInfo
*)This
);
7174 static HRESULT WINAPI
ITypeComp_fnBind(
7179 ITypeInfo
** ppTInfo
,
7180 DESCKIND
* pDescKind
,
7183 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7184 const TLBFuncDesc
*pFDesc
;
7185 const TLBVarDesc
*pVDesc
;
7186 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
7188 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7190 *pDescKind
= DESCKIND_NONE
;
7191 pBindPtr
->lpfuncdesc
= NULL
;
7194 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
7195 if (!strcmpiW(pFDesc
->Name
, szName
)) {
7196 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
7199 /* name found, but wrong flags */
7200 hr
= TYPE_E_TYPEMISMATCH
;
7205 HRESULT hr
= TLB_AllocAndInitFuncDesc(
7207 &pBindPtr
->lpfuncdesc
,
7208 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
7211 *pDescKind
= DESCKIND_FUNCDESC
;
7212 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7213 ITypeInfo_AddRef(*ppTInfo
);
7216 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
7217 if (!strcmpiW(pVDesc
->Name
, szName
)) {
7218 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
7221 *pDescKind
= DESCKIND_VARDESC
;
7222 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7223 ITypeInfo_AddRef(*ppTInfo
);
7228 /* FIXME: search each inherited interface, not just the first */
7229 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypelist
) {
7230 /* recursive search */
7234 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
7237 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
7238 ITypeInfo_Release(pTInfo
);
7242 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7243 ITypeComp_Release(pTComp
);
7246 WARN("Could not search inherited interface!\n");
7248 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
7252 static HRESULT WINAPI
ITypeComp_fnBindType(
7256 ITypeInfo
** ppTInfo
,
7257 ITypeComp
** ppTComp
)
7259 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
7261 /* strange behaviour (does nothing) but like the
7264 if (!ppTInfo
|| !ppTComp
)
7273 static const ITypeCompVtbl tcompvt
=
7276 ITypeComp_fnQueryInterface
,
7278 ITypeComp_fnRelease
,
7281 ITypeComp_fnBindType