4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
44 * -. lousy fatal error handling
49 #include "wine/port.h"
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
69 #include "wine/unicode.h"
72 #include "wine/debug.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
91 WORD type_id
; /* Type identifier */
92 WORD count
; /* Number of resources of this type */
93 DWORD resloader
; /* SetResourceHandler() */
99 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
100 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
102 /****************************************************************************
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
108 #ifdef WORDS_BIGENDIAN
109 static WORD
FromLEWord(WORD p_iVal
)
111 return (((p_iVal
& 0x00FF) << 8) |
112 ((p_iVal
& 0xFF00) >> 8));
116 static DWORD
FromLEDWord(DWORD p_iVal
)
118 return (((p_iVal
& 0x000000FF) << 24) |
119 ((p_iVal
& 0x0000FF00) << 8) |
120 ((p_iVal
& 0x00FF0000) >> 8) |
121 ((p_iVal
& 0xFF000000) >> 24));
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val
, int p_iSize
)
141 p_iSize
/= sizeof(WORD
);
144 *Val
= FromLEWord(*Val
);
151 static void FromLEDWords(void *p_Val
, int p_iSize
)
155 p_iSize
/= sizeof(DWORD
);
158 *Val
= FromLEDWord(*Val
);
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
169 * Find a typelib key which matches a requested maj.min version.
171 static BOOL
find_typelib_key( REFGUID guid
, WORD wMaj
, WORD
*wMin
)
173 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
180 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
181 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
186 len
= sizeof(key_name
);
188 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
192 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
201 break; /* exact match */
203 if (v_min
> best_min
) best_min
= v_min
;
206 len
= sizeof(key_name
);
217 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
218 /* buffer must be at least 60 characters long */
219 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
221 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
222 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
224 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
225 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
226 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
230 /* get the path of an interface key, in the form "Interface\\<guid>" */
231 /* buffer must be at least 50 characters long */
232 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
234 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
236 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
237 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
241 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
242 /* buffer must be at least 16 characters long */
243 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
245 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
246 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
247 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
249 sprintfW( buffer
, LcidFormatW
, lcid
);
252 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
253 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
255 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
261 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
264 /****************************************************************************
265 * QueryPathOfRegTypeLib [OLEAUT32.164]
267 * Gets the path to a registered type library.
270 * guid [I] referenced guid
271 * wMaj [I] major version
272 * wMin [I] minor version
274 * path [O] path of typelib
278 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
279 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
282 HRESULT WINAPI
QueryPathOfRegTypeLib(
289 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
293 WCHAR Path
[MAX_PATH
];
296 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
298 if (!find_typelib_key( guid
, wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
299 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
301 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
302 if (res
== ERROR_FILE_NOT_FOUND
)
304 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
305 return TYPE_E_LIBNOTREGISTERED
;
307 else if (res
!= ERROR_SUCCESS
)
309 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
310 return TYPE_E_REGISTRYACCESS
;
315 LONG dwPathLen
= sizeof(Path
);
317 get_lcid_subkey( myLCID
, SYS_WIN32
, buffer
);
319 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
323 else if (myLCID
== lcid
)
325 /* try with sub-langid */
326 myLCID
= SUBLANGID(lcid
);
328 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
330 /* try with system langid */
340 *path
= SysAllocString( Path
);
345 TRACE_(typelib
)("-- 0x%08x\n", hr
);
349 /******************************************************************************
350 * CreateTypeLib [OLEAUT32.160] creates a typelib
356 HRESULT WINAPI
CreateTypeLib(
357 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
359 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
363 /******************************************************************************
364 * LoadTypeLib [OLEAUT32.161]
366 * Loads a type library
369 * szFile [I] Name of file to load from.
370 * pptLib [O] Pointer that receives ITypeLib object on success.
377 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
379 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
381 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
382 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
385 /******************************************************************************
386 * LoadTypeLibEx [OLEAUT32.183]
388 * Loads and optionally registers a type library
394 HRESULT WINAPI
LoadTypeLibEx(
395 LPCOLESTR szFile
, /* [in] Name of file to load from */
396 REGKIND regkind
, /* [in] Specify kind of registration */
397 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
399 WCHAR szPath
[MAX_PATH
+1];
402 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
406 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
411 case REGKIND_DEFAULT
:
412 /* don't register typelibs supplied with full path. Experimentation confirms the following */
413 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
414 (szFile
[0] && (szFile
[1] == ':'))) break;
415 /* else fall-through */
417 case REGKIND_REGISTER
:
418 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
420 IUnknown_Release(*pptLib
);
428 TRACE(" returns %08x\n",res
);
432 /******************************************************************************
433 * LoadRegTypeLib [OLEAUT32.162]
435 * Loads a registered type library.
438 * rguid [I] GUID of the registered type library.
439 * wVerMajor [I] major version.
440 * wVerMinor [I] minor version.
441 * lcid [I] locale ID.
442 * ppTLib [O] pointer that receives an ITypeLib object on success.
446 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
449 HRESULT WINAPI
LoadRegTypeLib(
461 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
465 res
= LoadTypeLib(bstr
, ppTLib
);
469 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
475 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
476 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
477 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
478 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
479 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
480 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
482 /******************************************************************************
483 * RegisterTypeLib [OLEAUT32.163]
484 * Adds information about a type library to the System Registry
486 * Docs: ITypeLib FAR * ptlib
487 * Docs: OLECHAR FAR* szFullPath
488 * Docs: OLECHAR FAR* szHelpDir
494 HRESULT WINAPI
RegisterTypeLib(
495 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
496 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
497 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
500 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
501 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
502 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
512 if (ptlib
== NULL
|| szFullPath
== NULL
)
515 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
518 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
521 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
522 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
526 /* Set the human-readable name of the typelib */
527 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
529 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
530 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
538 /* Make up the name of the typelib path subkey */
539 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
541 /* Create the typelib path subkey */
542 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
543 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
545 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
546 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
554 /* Create the flags subkey */
555 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
556 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
558 /* FIXME: is %u correct? */
559 static const WCHAR formatW
[] = {'%','u',0};
561 sprintfW(buf
, formatW
, attr
->wLibFlags
);
562 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
563 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
571 /* create the helpdir subkey */
572 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
573 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
575 BOOL freeHelpDir
= FALSE
;
578 /* if we created a new key, and helpDir was null, set the helpdir
579 to the directory which contains the typelib. However,
580 if we just opened an existing key, we leave the helpdir alone */
581 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
582 szHelpDir
= SysAllocString(szFullPath
);
583 pIndexStr
= strrchrW(szHelpDir
, '\\');
590 /* if we have an szHelpDir, set it! */
591 if (szHelpDir
!= NULL
) {
592 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
593 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
599 if (freeHelpDir
) SysFreeString(szHelpDir
);
611 /* register OLE Automation-compatible interfaces for this typelib */
612 types
= ITypeLib_GetTypeInfoCount(ptlib
);
613 for (tidx
=0; tidx
<types
; tidx
++) {
614 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
615 LPOLESTR name
= NULL
;
616 ITypeInfo
*tinfo
= NULL
;
618 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
621 case TKIND_INTERFACE
:
622 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
623 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
627 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
628 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
632 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
637 TYPEATTR
*tattr
= NULL
;
638 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
641 TRACE_(typelib
)("guid=%s, flags=%04x (",
642 debugstr_guid(&tattr
->guid
),
645 if (TRACE_ON(typelib
)) {
646 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
666 if (tattr
->wTypeFlags
& (TYPEFLAG_FOLEAUTOMATION
|TYPEFLAG_FDUAL
|TYPEFLAG_FDISPATCHABLE
))
668 /* register interface<->typelib coupling */
669 get_interface_key( &tattr
->guid
, keyName
);
670 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
671 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
674 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
675 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
677 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
678 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
679 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
680 (const BYTE
*)PSOA
, sizeof PSOA
);
684 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
685 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
686 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
687 (const BYTE
*)PSOA
, sizeof PSOA
);
691 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
692 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
695 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
696 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
698 StringFromGUID2(&attr
->guid
, buffer
, 40);
699 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
700 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
701 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
702 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
703 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
711 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
714 ITypeInfo_Release(tinfo
);
721 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
727 /******************************************************************************
728 * UnRegisterTypeLib [OLEAUT32.186]
729 * Removes information about a type library from the System Registry
736 HRESULT WINAPI
UnRegisterTypeLib(
737 REFGUID libid
, /* [in] Guid of the library */
738 WORD wVerMajor
, /* [in] major version */
739 WORD wVerMinor
, /* [in] minor version */
740 LCID lcid
, /* [in] locale id */
743 BSTR tlibPath
= NULL
;
746 WCHAR subKeyName
[50];
749 BOOL deleteOtherStuff
;
752 TYPEATTR
* typeAttr
= NULL
;
754 ITypeInfo
* typeInfo
= NULL
;
755 ITypeLib
* typeLib
= NULL
;
758 TRACE("(IID: %s)\n",debugstr_guid(libid
));
760 /* Create the path to the key */
761 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
763 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
)
765 TRACE("Unsupported syskind %i\n", syskind
);
766 result
= E_INVALIDARG
;
770 /* get the path to the typelib on disk */
771 if (QueryPathOfRegTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, &tlibPath
) != S_OK
) {
772 result
= E_INVALIDARG
;
776 /* Try and open the key to the type library. */
777 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
778 result
= E_INVALIDARG
;
782 /* Try and load the type library */
783 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
)) {
784 result
= TYPE_E_INVALIDSTATE
;
788 /* remove any types registered with this typelib */
789 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
790 for (i
=0; i
<numTypes
; i
++) {
791 /* get the kind of type */
792 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
796 /* skip non-interfaces, and get type info for the type */
797 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
800 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
803 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
807 /* the path to the type */
808 get_interface_key( &typeAttr
->guid
, subKeyName
);
810 /* Delete its bits */
811 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != ERROR_SUCCESS
) {
814 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
815 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
816 RegDeleteKeyW(subKey
, TypeLibW
);
819 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
822 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
824 if (typeInfo
) ITypeInfo_Release(typeInfo
);
828 /* Now, delete the type library path subkey */
829 get_lcid_subkey( lcid
, syskind
, subKeyName
);
830 RegDeleteKeyW(key
, subKeyName
);
831 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
832 RegDeleteKeyW(key
, subKeyName
);
834 /* check if there is anything besides the FLAGS/HELPDIR keys.
835 If there is, we don't delete them */
836 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
837 deleteOtherStuff
= TRUE
;
839 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
840 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
842 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
843 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
844 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
845 deleteOtherStuff
= FALSE
;
849 /* only delete the other parts of the key if we're absolutely sure */
850 if (deleteOtherStuff
) {
851 RegDeleteKeyW(key
, FLAGSW
);
852 RegDeleteKeyW(key
, HELPDIRW
);
856 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
857 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
858 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
862 SysFreeString(tlibPath
);
863 if (typeLib
) ITypeLib_Release(typeLib
);
864 if (subKey
) RegCloseKey(subKey
);
865 if (key
) RegCloseKey(key
);
869 /*======================= ITypeLib implementation =======================*/
871 typedef struct tagTLBCustData
875 struct tagTLBCustData
* next
;
878 /* data structure for import typelibs */
879 typedef struct tagTLBImpLib
881 int offset
; /* offset in the file (MSFT)
882 offset in nametable (SLTG)
883 just used to identify library while reading
885 GUID guid
; /* libid */
886 BSTR name
; /* name */
888 LCID lcid
; /* lcid of imported typelib */
890 WORD wVersionMajor
; /* major version number */
891 WORD wVersionMinor
; /* minor version number */
893 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
894 NULL if not yet loaded */
895 struct tagTLBImpLib
* next
;
898 /* internal ITypeLib data */
899 typedef struct tagITypeLibImpl
901 const ITypeLib2Vtbl
*lpVtbl
;
902 const ITypeCompVtbl
*lpVtblTypeComp
;
904 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
906 /* strings can be stored in tlb as multibyte strings BUT they are *always*
907 * exported to the application as a UNICODE string.
913 unsigned long dwHelpContext
;
914 int TypeInfoCount
; /* nr of typeinfo's in librarry */
915 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
916 int ctCustData
; /* number of items in cust data list */
917 TLBCustData
* pCustData
; /* linked list to cust data */
918 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
919 int ctTypeDesc
; /* number of items in type desc array */
920 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
921 library. Only used while reading MSFT
923 struct list ref_list
; /* list of ref types in this typelib */
924 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
927 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
928 struct tagITypeLibImpl
*next
, *prev
;
933 static const ITypeLib2Vtbl tlbvt
;
934 static const ITypeCompVtbl tlbtcvt
;
936 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
938 return (ITypeLibImpl
*)((char*)iface
- FIELD_OFFSET(ITypeLibImpl
, lpVtblTypeComp
));
941 /* ITypeLib methods */
942 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
943 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
945 /*======================= ITypeInfo implementation =======================*/
947 /* data for referenced types */
948 typedef struct tagTLBRefType
950 INT index
; /* Type index for internal ref or for external ref
951 it the format is SLTG. -2 indicates to
954 GUID guid
; /* guid of the referenced type */
955 /* if index == TLB_REF_USE_GUID */
957 HREFTYPE reference
; /* The href of this ref */
958 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
959 TLB_REF_INTERNAL for internal refs
960 TLB_REF_NOT_FOUND for broken refs */
965 #define TLB_REF_USE_GUID -2
967 #define TLB_REF_INTERNAL (void*)-2
968 #define TLB_REF_NOT_FOUND (void*)-1
970 /* internal Parameter data */
971 typedef struct tagTLBParDesc
975 TLBCustData
* pCustData
; /* linked list to cust data */
978 /* internal Function data */
979 typedef struct tagTLBFuncDesc
981 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
982 BSTR Name
; /* the name of this function */
983 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
985 int HelpStringContext
;
987 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
989 TLBCustData
* pCustData
; /* linked list to cust data; */
990 struct tagTLBFuncDesc
* next
;
993 /* internal Variable data */
994 typedef struct tagTLBVarDesc
996 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
997 BSTR Name
; /* the name of this variable */
999 int HelpStringContext
; /* FIXME: where? */
1002 TLBCustData
* pCustData
;/* linked list to cust data; */
1003 struct tagTLBVarDesc
* next
;
1006 /* internal implemented interface data */
1007 typedef struct tagTLBImplType
1009 HREFTYPE hRef
; /* hRef of interface */
1010 int implflags
; /* IMPLFLAG_*s */
1012 TLBCustData
* pCustData
;/* linked list to custom data; */
1013 struct tagTLBImplType
*next
;
1016 /* internal TypeInfo data */
1017 typedef struct tagITypeInfoImpl
1019 const ITypeInfo2Vtbl
*lpVtbl
;
1020 const ITypeCompVtbl
*lpVtblTypeComp
;
1022 BOOL no_free_data
; /* don't free data structures */
1023 TYPEATTR TypeAttr
; /* _lots_ of type information. */
1024 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1025 int index
; /* index in this typelib; */
1026 HREFTYPE hreftype
; /* hreftype for app object binding */
1027 /* type libs seem to store the doc strings in ascii
1028 * so why should we do it in unicode?
1033 unsigned long dwHelpContext
;
1034 unsigned long dwHelpStringContext
;
1037 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
1040 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
1042 /* Implemented Interfaces */
1043 TLBImplType
* impltypelist
;
1046 TLBCustData
* pCustData
; /* linked list to cust data; */
1047 struct tagITypeInfoImpl
* next
;
1050 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1052 return (ITypeInfoImpl
*)((char*)iface
- FIELD_OFFSET(ITypeInfoImpl
, lpVtblTypeComp
));
1055 static const ITypeInfo2Vtbl tinfvt
;
1056 static const ITypeCompVtbl tcompvt
;
1058 static ITypeInfo2
* ITypeInfo_Constructor(void);
1060 typedef struct tagTLBContext
1062 unsigned int oStart
; /* start of TLB in file */
1063 unsigned int pos
; /* current pos */
1064 unsigned int length
; /* total length */
1065 void *mapping
; /* memory mapping */
1066 MSFT_SegDir
* pTblDir
;
1067 ITypeLibImpl
* pLibInfo
;
1071 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
, int offset
);
1076 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1077 if (pTD
->vt
& VT_RESERVED
)
1078 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1079 if (pTD
->vt
& VT_BYREF
)
1080 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1081 if (pTD
->vt
& VT_ARRAY
)
1082 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1083 if (pTD
->vt
& VT_VECTOR
)
1084 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1085 switch(pTD
->vt
& VT_TYPEMASK
) {
1086 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1087 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1088 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1089 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1090 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1091 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1092 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1093 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1094 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1095 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1096 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1097 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1098 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1099 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1100 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1101 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1102 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1103 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1104 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1105 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1106 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1107 pTD
->u
.hreftype
); break;
1108 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1109 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1110 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1111 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1113 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1114 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1116 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1117 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1118 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1121 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1125 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1127 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1128 dump_TypeDesc(&edesc
->tdesc
,buf
);
1129 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1130 MESSAGE("\t\tu.paramdesc.wParamFlags");
1131 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1132 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1133 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1134 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1135 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1136 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1137 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1138 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1139 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1141 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1143 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1144 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1145 MESSAGE("Param %d:\n",i
);
1146 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1148 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1149 switch (funcdesc
->funckind
) {
1150 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1151 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1152 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1153 case FUNC_STATIC
: MESSAGE("static");break;
1154 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1155 default: MESSAGE("unknown");break;
1157 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1158 switch (funcdesc
->invkind
) {
1159 case INVOKE_FUNC
: MESSAGE("func");break;
1160 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1161 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1162 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1164 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1165 switch (funcdesc
->callconv
) {
1166 case CC_CDECL
: MESSAGE("cdecl");break;
1167 case CC_PASCAL
: MESSAGE("pascal");break;
1168 case CC_STDCALL
: MESSAGE("stdcall");break;
1169 case CC_SYSCALL
: MESSAGE("syscall");break;
1172 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1173 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1174 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1176 MESSAGE("\telemdescFunc (return value type):\n");
1177 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1180 static const char * const typekind_desc
[] =
1193 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1196 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1197 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1198 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1201 dump_FUNCDESC(&(pfd
->funcdesc
));
1203 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1204 MESSAGE("\tentry: %s\n", (pfd
->Entry
== (void *)-1) ? "invalid" : debugstr_w(pfd
->Entry
));
1206 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
)
1210 dump_TLBFuncDescOne(pfd
);
1214 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
)
1218 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1223 static void dump_TLBImpLib(const TLBImpLib
*import
)
1225 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1226 debugstr_w(import
->name
));
1227 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1228 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1231 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1235 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1237 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1238 if(ref
->index
== -1)
1239 TRACE_(typelib
)("%s\n", debugstr_guid(&(ref
->guid
)));
1241 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1243 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1245 TRACE_(typelib
)("in lib\n");
1246 dump_TLBImpLib(ref
->pImpTLInfo
);
1251 static void dump_TLBImplType(const TLBImplType
* impl
)
1255 "implementing/inheriting interface hRef = %x implflags %x\n",
1256 impl
->hRef
, impl
->implflags
);
1261 static void dump_Variant(const VARIANT
* pvar
)
1265 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1269 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1270 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1272 TRACE(",%p", V_BYREF(pvar
));
1274 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1276 TRACE(",%p", V_ARRAY(pvar
));
1278 else switch (V_TYPE(pvar
))
1280 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1281 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1282 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1283 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1285 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1287 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1288 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1289 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1290 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1291 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1292 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1293 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1294 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1295 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1296 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1297 V_CY(pvar
).s
.Lo
); break;
1299 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1300 TRACE(",<invalid>");
1302 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1303 st
.wHour
, st
.wMinute
, st
.wSecond
);
1307 case VT_USERDEFINED
:
1309 case VT_NULL
: break;
1310 default: TRACE(",?"); break;
1316 static void dump_DispParms(const DISPPARAMS
* pdp
)
1320 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1322 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1324 TRACE("named args:\n");
1325 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1326 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1329 if (pdp
->cArgs
&& pdp
->rgvarg
)
1332 for (index
= 0; index
< pdp
->cArgs
; index
++)
1333 dump_Variant( &pdp
->rgvarg
[index
] );
1337 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1339 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1340 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1341 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1342 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1343 TRACE("fct:%u var:%u impl:%u\n",
1344 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1345 TRACE("wTypeFlags: 0x%04x\n", pty
->TypeAttr
.wTypeFlags
);
1346 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1347 if (pty
->TypeAttr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(pty
->DllName
));
1349 dump_TLBFuncDesc(pty
->funclist
);
1350 dump_TLBVarDesc(pty
->varlist
);
1351 dump_TLBImplType(pty
->impltypelist
);
1354 static void dump_VARDESC(const VARDESC
*v
)
1356 MESSAGE("memid %d\n",v
->memid
);
1357 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1358 MESSAGE("oInst %d\n",v
->u
.oInst
);
1359 dump_ELEMDESC(&(v
->elemdescVar
));
1360 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1361 MESSAGE("varkind %d\n",v
->varkind
);
1364 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1366 /* VT_LPWSTR is largest type that */
1367 /* may appear in type description*/
1368 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1369 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1370 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1371 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1372 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1373 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1377 static void TLB_abort(void)
1382 static void * TLB_Alloc(unsigned size
) __WINE_ALLOC_SIZE(1);
1383 static void * TLB_Alloc(unsigned size
)
1386 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1388 ERR("cannot allocate memory\n");
1393 static void TLB_Free(void * ptr
)
1395 HeapFree(GetProcessHeap(), 0, ptr
);
1398 /* returns the size required for a deep copy of a typedesc into a
1400 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1404 if (alloc_initial_space
)
1405 size
+= sizeof(TYPEDESC
);
1411 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1414 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1415 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1421 /* deep copy a typedesc into a flat buffer */
1422 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1427 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1436 dest
->u
.lptdesc
= buffer
;
1437 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1440 dest
->u
.lpadesc
= buffer
;
1441 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1442 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1443 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1449 /* free custom data allocated by MSFT_CustData */
1450 static inline void TLB_FreeCustData(TLBCustData
*pCustData
)
1452 TLBCustData
*pCustDataNext
;
1453 for (; pCustData
; pCustData
= pCustDataNext
)
1455 VariantClear(&pCustData
->data
);
1457 pCustDataNext
= pCustData
->next
;
1458 TLB_Free(pCustData
);
1462 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1467 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1468 ret
= SysAllocStringLen(NULL
, len
- 1);
1469 if (!ret
) return ret
;
1470 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1474 /**********************************************************************
1476 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1478 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
1483 static inline void MSFT_Seek(TLBContext
*pcx
, long where
)
1485 if (where
!= DO_NOT_SEEK
)
1487 where
+= pcx
->oStart
;
1488 if (where
> pcx
->length
)
1491 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1499 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1501 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1502 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1504 MSFT_Seek(pcx
, where
);
1505 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1506 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1511 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1516 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1517 FromLEDWords(buffer
, ret
);
1522 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1527 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1528 FromLEWords(buffer
, ret
);
1533 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1535 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1536 memset(pGuid
,0, sizeof(GUID
));
1539 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1540 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1541 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1542 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1543 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1546 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
1548 MSFT_NameIntro niName
;
1552 ERR_(typelib
)("bad offset %d\n", offset
);
1556 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1557 pcx
->pTblDir
->pNametab
.offset
+offset
);
1559 return niName
.hreftype
;
1562 static BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1565 MSFT_NameIntro niName
;
1567 BSTR bstrName
= NULL
;
1571 ERR_(typelib
)("bad offset %d\n", offset
);
1574 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1575 pcx
->pTblDir
->pNametab
.offset
+offset
);
1576 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1577 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1578 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1579 name
[niName
.namelen
& 0xff]='\0';
1581 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1584 /* no invalid characters in string */
1587 bstrName
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1589 /* don't check for invalid character since this has been done previously */
1590 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, bstrName
, lengthInChars
);
1594 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1598 static BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1605 if(offset
<0) return NULL
;
1606 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1607 if(length
<= 0) return 0;
1608 string
=TLB_Alloc(length
+1);
1609 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1610 string
[length
]='\0';
1612 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1613 string
, -1, NULL
, 0);
1615 /* no invalid characters in string */
1618 bstr
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1620 /* don't check for invalid character since this has been done previously */
1621 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, bstr
, lengthInChars
);
1625 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1629 * read a value and fill a VARIANT structure
1631 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1635 TRACE_(typelib
)("\n");
1637 if(offset
<0) { /* data are packed in here */
1638 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1639 V_I4(pVar
) = offset
& 0x3ffffff;
1642 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1643 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1644 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1645 switch (V_VT(pVar
)){
1646 case VT_EMPTY
: /* FIXME: is this right? */
1647 case VT_NULL
: /* FIXME: is this right? */
1648 case VT_I2
: /* this should not happen */
1659 case VT_VOID
: /* FIXME: is this right? */
1667 case VT_DECIMAL
: /* FIXME: is this right? */
1670 /* pointer types with known behaviour */
1673 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1676 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
1679 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
1681 nullPos
= MSFT_Tell(pcx
);
1682 size
= nullPos
- origPos
;
1683 MSFT_Seek(pcx
, origPos
);
1685 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1686 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1687 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1688 /* FIXME: do we need a AtoW conversion here? */
1689 V_UNION(pVar
, bstrVal
[size
])='\0';
1690 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1694 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1701 case VT_USERDEFINED
:
1707 case VT_STREAMED_OBJECT
:
1708 case VT_STORED_OBJECT
:
1709 case VT_BLOB_OBJECT
:
1714 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1718 if(size
>0) /* (big|small) endian correct? */
1719 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1723 * create a linked list with custom data
1725 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1731 TRACE_(typelib
)("\n");
1735 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1736 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1737 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1738 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1739 /* add new custom data at head of the list */
1740 pNew
->next
=*ppCustData
;
1742 offset
= entry
.next
;
1747 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1751 pTd
->vt
=type
& VT_TYPEMASK
;
1753 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1755 if(pTd
->vt
== VT_USERDEFINED
)
1756 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, pTd
->u
.hreftype
);
1758 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1761 static void MSFT_ResolveReferencedTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, TYPEDESC
*lpTypeDesc
)
1763 /* resolve referenced type if any */
1766 switch (lpTypeDesc
->vt
)
1769 lpTypeDesc
= lpTypeDesc
->u
.lptdesc
;
1773 lpTypeDesc
= & (lpTypeDesc
->u
.lpadesc
->tdescElem
);
1776 case VT_USERDEFINED
:
1777 MSFT_DoRefType(pcx
, pTI
->pTypeLib
,
1778 lpTypeDesc
->u
.hreftype
);
1790 MSFT_DoFuncs(TLBContext
* pcx
,
1795 TLBFuncDesc
** pptfd
)
1798 * member information is stored in a data structure at offset
1799 * indicated by the memoffset field of the typeinfo structure
1800 * There are several distinctive parts.
1801 * The first part starts with a field that holds the total length
1802 * of this (first) part excluding this field. Then follow the records,
1803 * for each member there is one record.
1805 * The first entry is always the length of the record (including this
1807 * The rest of the record depends on the type of the member. If there is
1808 * a field indicating the member type (function, variable, interface, etc)
1809 * I have not found it yet. At this time we depend on the information
1810 * in the type info and the usual order how things are stored.
1812 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1815 * Third is an equal sized array with file offsets to the name entry
1818 * The fourth and last (?) part is an array with offsets to the records
1819 * in the first part of this file segment.
1822 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1823 int recoffset
= offset
+ sizeof(INT
);
1825 char *recbuf
= HeapAlloc(GetProcessHeap(), 0, 0xffff);
1826 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1827 TLBFuncDesc
*ptfd_prev
= NULL
;
1829 TRACE_(typelib
)("\n");
1831 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1833 for ( i
= 0; i
< cFuncs
; i
++ )
1835 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1837 /* name, eventually add to a hash table */
1838 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1839 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1841 /* nameoffset is sometimes -1 on the second half of a propget/propput
1842 * pair of functions */
1843 if ((nameoffset
== -1) && (i
> 0))
1844 (*pptfd
)->Name
= SysAllocString(ptfd_prev
->Name
);
1846 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1848 /* read the function information record */
1849 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1851 reclength
&= 0xffff;
1853 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1855 /* do the attributes */
1856 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1859 if ( nrattributes
> 0 )
1861 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1863 if ( nrattributes
> 1 )
1865 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1866 pFuncRec
->OptAttr
[1]) ;
1868 if ( nrattributes
> 2 )
1870 if ( pFuncRec
->FKCCIC
& 0x2000 )
1872 if (HIWORD(pFuncRec
->OptAttr
[2]) != 0)
1873 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec
->OptAttr
[2]);
1874 (*pptfd
)->Entry
= (BSTR
)pFuncRec
->OptAttr
[2];
1878 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1879 pFuncRec
->OptAttr
[2]);
1881 if( nrattributes
> 5 )
1883 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1885 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1888 pFuncRec
->OptAttr
[6],
1889 &(*pptfd
)->pCustData
);
1895 (*pptfd
)->Entry
= (BSTR
)-1;
1900 /* fill the FuncDesc Structure */
1901 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1902 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1904 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1905 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1906 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1907 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1908 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1909 (*pptfd
)->funcdesc
.oVft
= (pFuncRec
->VtableOffset
* sizeof(void *))/4;
1910 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1914 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1916 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
);
1918 /* do the parameters/arguments */
1919 if(pFuncRec
->nrargs
)
1922 MSFT_ParameterInfo paraminfo
;
1924 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1925 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1927 (*pptfd
)->pParamDesc
=
1928 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1930 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1931 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1933 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1935 ELEMDESC
*elemdesc
= &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1942 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1945 if (paraminfo
.oName
== -1)
1946 /* this occurs for [propput] or [propget] methods, so
1947 * we should just set the name of the parameter to the
1948 * name of the method. */
1949 (*pptfd
)->pParamDesc
[j
].Name
= SysAllocString((*pptfd
)->Name
);
1951 (*pptfd
)->pParamDesc
[j
].Name
=
1952 MSFT_ReadName( pcx
, paraminfo
.oName
);
1953 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w((*pptfd
)->pParamDesc
[j
].Name
));
1955 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
1958 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
1959 (pFuncRec
->FKCCIC
& 0x1000) )
1961 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1963 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1965 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
1967 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1968 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1970 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1974 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
1976 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1979 pFuncRec
->OptAttr
[7+j
],
1980 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1983 /* SEEK value = jump to offset,
1984 * from there jump to the end of record,
1985 * go back by (j-1) arguments
1987 MSFT_ReadLEDWords( ¶minfo
,
1988 sizeof(MSFT_ParameterInfo
), pcx
,
1989 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1990 * sizeof(MSFT_ParameterInfo
)));
1994 /* scode is not used: archaic win16 stuff FIXME: right? */
1995 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1996 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1999 pptfd
= & ((*pptfd
)->next
);
2000 recoffset
+= reclength
;
2002 HeapFree(GetProcessHeap(), 0, recbuf
);
2005 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2006 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2008 int infolen
, nameoffset
, reclength
;
2010 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
2014 TRACE_(typelib
)("\n");
2016 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2017 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2018 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2019 recoffset
+= offset
+sizeof(INT
);
2020 for(i
=0;i
<cVars
;i
++){
2021 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
2022 /* name, eventually add to a hash table */
2023 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2024 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2025 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
2026 /* read the variable information record */
2027 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
2029 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
2031 if(reclength
>(6*sizeof(INT
)) )
2032 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
2033 if(reclength
>(7*sizeof(INT
)) )
2034 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
2035 if(reclength
>(8*sizeof(INT
)) )
2036 if(reclength
>(9*sizeof(INT
)) )
2037 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
2038 /* fill the VarDesc Structure */
2039 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
2040 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2041 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
2042 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
2043 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2044 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
2045 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2046 if(pVarRec
->VarKind
== VAR_CONST
){
2047 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
2048 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
2049 pVarRec
->OffsValue
, pcx
);
2051 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2052 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptvd
)->vardesc
.elemdescVar
.tdesc
);
2053 pptvd
=&((*pptvd
)->next
);
2054 recoffset
+= reclength
;
2057 /* fill in data for a hreftype (offset). When the referenced type is contained
2058 * in the typelib, it's just an (file) offset in the type info base dir.
2059 * If comes from import, it's an offset+1 in the ImpInfo table
2061 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
,
2066 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2068 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
2070 if(ref
->reference
== offset
) return;
2073 ref
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref
));
2074 list_add_tail(&pTL
->ref_list
, &ref
->entry
);
2076 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2077 /* external typelib */
2078 MSFT_ImpInfo impinfo
;
2079 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
2081 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2083 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2084 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2085 while (pImpLib
){ /* search the known offsets of all import libraries */
2086 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
2087 pImpLib
=pImpLib
->next
;
2090 ref
->reference
= offset
;
2091 ref
->pImpTLInfo
= pImpLib
;
2092 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2093 MSFT_ReadGuid(&ref
->guid
, impinfo
.oGuid
, pcx
);
2094 TRACE("importing by guid %s\n", debugstr_guid(&ref
->guid
));
2095 ref
->index
= TLB_REF_USE_GUID
;
2097 ref
->index
= impinfo
.oGuid
;
2099 ERR("Cannot find a reference\n");
2100 ref
->reference
= -1;
2101 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2104 /* in this typelib */
2105 ref
->index
= MSFT_HREFTYPE_INDEX(offset
);
2106 ref
->reference
= offset
;
2107 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
2111 /* process Implemented Interfaces of a com class */
2112 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2116 MSFT_RefRecord refrec
;
2117 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
2119 TRACE_(typelib
)("\n");
2121 for(i
=0;i
<count
;i
++){
2122 if(offset
<0) break; /* paranoia */
2123 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
2124 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2125 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, refrec
.reftype
);
2126 (*ppImpl
)->hRef
= refrec
.reftype
;
2127 (*ppImpl
)->implflags
=refrec
.flags
;
2128 (*ppImpl
)->ctCustData
=
2129 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
2130 offset
=refrec
.onext
;
2131 ppImpl
=&((*ppImpl
)->next
);
2135 * process a typeinfo record
2137 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2140 ITypeLibImpl
* pLibInfo
)
2142 MSFT_TypeInfoBase tiBase
;
2143 ITypeInfoImpl
*ptiRet
;
2145 TRACE_(typelib
)("count=%u\n", count
);
2147 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
2148 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2149 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2151 /* this is where we are coming from */
2152 ptiRet
->pTypeLib
= pLibInfo
;
2153 ptiRet
->index
=count
;
2154 /* fill in the typeattr fields */
2156 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2157 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2158 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2159 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2160 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2161 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2162 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2163 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2164 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2165 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2166 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2167 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2168 ptiRet
->TypeAttr
.cbSizeVft
=(tiBase
.cbSizeVft
* sizeof(void *))/4; /* FIXME: this is only the non inherited part */
2169 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2170 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2171 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2174 /* IDLDESC idldescType; *//* never saw this one != zero */
2176 /* name, eventually add to a hash table */
2177 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2178 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2179 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2181 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2182 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2183 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2185 if (ptiRet
->TypeAttr
.typekind
== TKIND_MODULE
)
2186 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2188 /* note: InfoType's Help file and HelpStringDll come from the containing
2189 * library. Further HelpString and Docstring appear to be the same thing :(
2192 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2193 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2194 ptiRet
->TypeAttr
.cVars
,
2195 tiBase
.memoffset
, & ptiRet
->funclist
);
2197 if(ptiRet
->TypeAttr
.cVars
>0 )
2198 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2199 ptiRet
->TypeAttr
.cVars
,
2200 tiBase
.memoffset
, & ptiRet
->varlist
);
2201 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2202 switch(ptiRet
->TypeAttr
.typekind
)
2205 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2208 case TKIND_DISPATCH
:
2209 /* This is not -1 when the interface is a non-base dual interface or
2210 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2211 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2215 if (tiBase
.datatype1
!= -1)
2217 ptiRet
->impltypelist
= TLB_Alloc(sizeof(TLBImplType
));
2218 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2219 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2223 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2224 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2225 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2230 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2232 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2233 debugstr_w(ptiRet
->Name
),
2234 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2235 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2236 if (TRACE_ON(typelib
))
2237 dump_TypeInfo(ptiRet
);
2242 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2243 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2244 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2247 static ITypeLibImpl
*tlb_cache_first
;
2248 static CRITICAL_SECTION cache_section
;
2249 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2251 0, 0, &cache_section
,
2252 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2253 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2255 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2258 typedef struct TLB_PEFile
2260 const IUnknownVtbl
*lpvtbl
;
2263 HRSRC typelib_resource
;
2264 HGLOBAL typelib_global
;
2265 LPVOID typelib_base
;
2268 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2270 if (IsEqualIID(riid
, &IID_IUnknown
))
2273 IUnknown_AddRef(iface
);
2277 return E_NOINTERFACE
;
2280 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2282 TLB_PEFile
*This
= (TLB_PEFile
*)iface
;
2283 return InterlockedIncrement(&This
->refs
);
2286 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2288 TLB_PEFile
*This
= (TLB_PEFile
*)iface
;
2289 ULONG refs
= InterlockedDecrement(&This
->refs
);
2292 if (This
->typelib_global
)
2293 FreeResource(This
->typelib_global
);
2295 FreeLibrary(This
->dll
);
2296 HeapFree(GetProcessHeap(), 0, This
);
2301 static const IUnknownVtbl TLB_PEFile_Vtable
=
2303 TLB_PEFile_QueryInterface
,
2308 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2312 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2314 return E_OUTOFMEMORY
;
2316 This
->lpvtbl
= &TLB_PEFile_Vtable
;
2319 This
->typelib_resource
= NULL
;
2320 This
->typelib_global
= NULL
;
2321 This
->typelib_base
= NULL
;
2323 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2324 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2328 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2329 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2330 if (This
->typelib_resource
)
2332 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2333 if (This
->typelib_global
)
2335 This
->typelib_base
= LockResource(This
->typelib_global
);
2337 if (This
->typelib_base
)
2339 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2340 *ppBase
= This
->typelib_base
;
2341 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2348 TLB_PEFile_Release((IUnknown
*)&This
->lpvtbl
);
2349 return TYPE_E_CANTLOADLIBRARY
;
2352 typedef struct TLB_NEFile
2354 const IUnknownVtbl
*lpvtbl
;
2356 LPVOID typelib_base
;
2359 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2361 if (IsEqualIID(riid
, &IID_IUnknown
))
2364 IUnknown_AddRef(iface
);
2368 return E_NOINTERFACE
;
2371 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2373 TLB_NEFile
*This
= (TLB_NEFile
*)iface
;
2374 return InterlockedIncrement(&This
->refs
);
2377 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2379 TLB_NEFile
*This
= (TLB_NEFile
*)iface
;
2380 ULONG refs
= InterlockedDecrement(&This
->refs
);
2383 HeapFree(GetProcessHeap(), 0, This
->typelib_base
);
2384 HeapFree(GetProcessHeap(), 0, This
);
2389 static const IUnknownVtbl TLB_NEFile_Vtable
=
2391 TLB_NEFile_QueryInterface
,
2396 /***********************************************************************
2397 * read_xx_header [internal]
2399 static int read_xx_header( HFILE lzfd
)
2401 IMAGE_DOS_HEADER mzh
;
2404 LZSeek( lzfd
, 0, SEEK_SET
);
2405 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
2407 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
2410 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2411 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
2414 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2416 if ( magic
[0] == 'N' && magic
[1] == 'E' )
2417 return IMAGE_OS2_SIGNATURE
;
2418 if ( magic
[0] == 'P' && magic
[1] == 'E' )
2419 return IMAGE_NT_SIGNATURE
;
2422 WARN("Can't handle %s files.\n", magic
);
2427 /***********************************************************************
2428 * find_ne_resource [internal]
2430 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
2431 DWORD
*resLen
, DWORD
*resOff
)
2433 IMAGE_OS2_HEADER nehd
;
2434 NE_TYPEINFO
*typeInfo
;
2435 NE_NAMEINFO
*nameInfo
;
2441 /* Read in NE header */
2442 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
2443 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
2445 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
2448 TRACE("No resources in NE dll\n" );
2452 /* Read in resource table */
2453 resTab
= HeapAlloc( GetProcessHeap(), 0, resTabSize
);
2454 if ( !resTab
) return FALSE
;
2456 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
2457 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
2459 HeapFree( GetProcessHeap(), 0, resTab
);
2464 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
2466 if (HIWORD(typeid) != 0) /* named type */
2468 BYTE len
= strlen( typeid );
2469 while (typeInfo
->type_id
)
2471 if (!(typeInfo
->type_id
& 0x8000))
2473 BYTE
*p
= resTab
+ typeInfo
->type_id
;
2474 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
2476 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2477 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2480 else /* numeric type id */
2482 WORD id
= LOWORD(typeid) | 0x8000;
2483 while (typeInfo
->type_id
)
2485 if (typeInfo
->type_id
== id
) goto found_type
;
2486 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2487 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2490 TRACE("No typeid entry found for %p\n", typeid );
2491 HeapFree( GetProcessHeap(), 0, resTab
);
2495 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
2497 if (HIWORD(resid
) != 0) /* named resource */
2499 BYTE len
= strlen( resid
);
2500 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2502 BYTE
*p
= resTab
+ nameInfo
->id
;
2503 if (nameInfo
->id
& 0x8000) continue;
2504 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
2507 else /* numeric resource id */
2509 WORD id
= LOWORD(resid
) | 0x8000;
2510 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2511 if (nameInfo
->id
== id
) goto found_name
;
2513 TRACE("No resid entry found for %p\n", typeid );
2514 HeapFree( GetProcessHeap(), 0, resTab
);
2518 /* Return resource data */
2519 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
2520 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
2522 HeapFree( GetProcessHeap(), 0, resTab
);
2526 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
2530 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2531 TLB_NEFile
*This
= NULL
;
2533 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2534 if (!This
) return E_OUTOFMEMORY
;
2536 This
->lpvtbl
= &TLB_NEFile_Vtable
;
2538 This
->typelib_base
= NULL
;
2540 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
2541 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
2543 DWORD reslen
, offset
;
2544 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
2546 This
->typelib_base
= HeapAlloc(GetProcessHeap(), 0, reslen
);
2547 if( !This
->typelib_base
)
2551 LZSeek( lzfd
, offset
, SEEK_SET
);
2552 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
2554 *ppBase
= This
->typelib_base
;
2555 *pdwTLBLength
= reslen
;
2556 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2562 if( lzfd
>= 0) LZClose( lzfd
);
2563 TLB_NEFile_Release((IUnknown
*)&This
->lpvtbl
);
2567 typedef struct TLB_Mapping
2569 const IUnknownVtbl
*lpvtbl
;
2573 LPVOID typelib_base
;
2576 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2578 if (IsEqualIID(riid
, &IID_IUnknown
))
2581 IUnknown_AddRef(iface
);
2585 return E_NOINTERFACE
;
2588 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
2590 TLB_Mapping
*This
= (TLB_Mapping
*)iface
;
2591 return InterlockedIncrement(&This
->refs
);
2594 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
2596 TLB_Mapping
*This
= (TLB_Mapping
*)iface
;
2597 ULONG refs
= InterlockedDecrement(&This
->refs
);
2600 if (This
->typelib_base
)
2601 UnmapViewOfFile(This
->typelib_base
);
2603 CloseHandle(This
->mapping
);
2604 if (This
->file
!= INVALID_HANDLE_VALUE
)
2605 CloseHandle(This
->file
);
2606 HeapFree(GetProcessHeap(), 0, This
);
2611 static const IUnknownVtbl TLB_Mapping_Vtable
=
2613 TLB_Mapping_QueryInterface
,
2618 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2622 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2624 return E_OUTOFMEMORY
;
2626 This
->lpvtbl
= &TLB_Mapping_Vtable
;
2628 This
->file
= INVALID_HANDLE_VALUE
;
2629 This
->mapping
= NULL
;
2630 This
->typelib_base
= NULL
;
2632 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
2633 if (INVALID_HANDLE_VALUE
!= This
->file
)
2635 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2638 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
2639 if(This
->typelib_base
)
2641 /* retrieve file size */
2642 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
2643 *ppBase
= This
->typelib_base
;
2644 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2650 IUnknown_Release((IUnknown
*)&This
->lpvtbl
);
2651 return TYPE_E_CANTLOADLIBRARY
;
2654 /****************************************************************************
2657 * find the type of the typelib file and map the typelib resource into
2660 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2661 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2662 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
2664 ITypeLibImpl
*entry
;
2667 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
2668 LPVOID pBase
= NULL
;
2669 DWORD dwTLBLength
= 0;
2670 IUnknown
*pFile
= NULL
;
2674 index_str
= strrchrW(pszFileName
, '\\');
2675 if(index_str
&& *++index_str
!= '\0')
2678 long idx
= strtolW(index_str
, &end_ptr
, 10);
2679 if(*end_ptr
== '\0')
2681 int str_len
= index_str
- pszFileName
- 1;
2683 file
= HeapAlloc(GetProcessHeap(), 0, (str_len
+ 1) * sizeof(WCHAR
));
2684 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
2689 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
2691 if(strchrW(file
, '\\'))
2693 lstrcpyW(pszPath
, file
);
2697 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
2698 pszPath
[len
] = '\\';
2699 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
2703 if(file
!= pszFileName
) HeapFree(GetProcessHeap(), 0, file
);
2705 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
2707 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2708 EnterCriticalSection(&cache_section
);
2709 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2711 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
2713 TRACE("cache hit\n");
2714 *ppTypeLib
= (ITypeLib2
*)entry
;
2715 ITypeLib_AddRef(*ppTypeLib
);
2716 LeaveCriticalSection(&cache_section
);
2720 LeaveCriticalSection(&cache_section
);
2722 /* now actually load and parse the typelib */
2724 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2725 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2726 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2727 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2728 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
2731 if (dwTLBLength
>= 4)
2733 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2734 if (dwSignature
== MSFT_SIGNATURE
)
2735 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2736 else if (dwSignature
== SLTG_SIGNATURE
)
2737 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2740 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
2741 ret
= TYPE_E_CANTLOADLIBRARY
;
2745 ret
= TYPE_E_CANTLOADLIBRARY
;
2746 IUnknown_Release(pFile
);
2750 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2752 TRACE("adding to cache\n");
2753 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath
)+1) * sizeof(WCHAR
));
2754 lstrcpyW(impl
->path
, pszPath
);
2755 /* We should really canonicalise the path here. */
2756 impl
->index
= index
;
2758 /* FIXME: check if it has added already in the meantime */
2759 EnterCriticalSection(&cache_section
);
2760 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2762 tlb_cache_first
= impl
;
2763 LeaveCriticalSection(&cache_section
);
2766 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
2771 /*================== ITypeLib(2) Methods ===================================*/
2773 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
2775 ITypeLibImpl
* pTypeLibImpl
;
2777 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2778 if (!pTypeLibImpl
) return NULL
;
2780 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2781 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2782 pTypeLibImpl
->ref
= 1;
2784 list_init(&pTypeLibImpl
->ref_list
);
2785 pTypeLibImpl
->dispatch_href
= -1;
2787 return pTypeLibImpl
;
2790 /****************************************************************************
2791 * ITypeLib2_Constructor_MSFT
2793 * loading an MSFT typelib from an in-memory image
2795 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2799 MSFT_Header tlbHeader
;
2800 MSFT_SegDir tlbSegDir
;
2801 ITypeLibImpl
* pTypeLibImpl
;
2803 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
2805 pTypeLibImpl
= TypeLibImpl_Constructor();
2806 if (!pTypeLibImpl
) return NULL
;
2808 /* get pointer to beginning of typelib data */
2812 cx
.pLibInfo
= pTypeLibImpl
;
2813 cx
.length
= dwTLBLength
;
2816 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2817 TRACE_(typelib
)("header:\n");
2818 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2819 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2820 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2823 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
2825 /* there is a small amount of information here until the next important
2827 * the segment directory . Try to calculate the amount of data */
2828 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2830 /* now read the segment directory */
2831 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2832 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2833 cx
.pTblDir
= &tlbSegDir
;
2835 /* just check two entries */
2836 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2838 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2839 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2843 /* now fill our internal data */
2844 /* TLIBATTR fields */
2845 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2847 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2848 /* Windows seems to have zero here, is this correct? */
2849 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2850 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader
.lcid
),0),0);
2852 pTypeLibImpl
->LibAttr
.lcid
= 0;
2854 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2855 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2856 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2857 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2859 /* name, eventually add to a hash table */
2860 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2863 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2864 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2866 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2869 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2870 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2873 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2876 if(tlbHeader
.CustomDataOffset
>= 0)
2878 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2881 /* fill in type descriptions */
2882 if(tlbSegDir
.pTypdescTab
.length
> 0)
2884 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2886 pTypeLibImpl
->ctTypeDesc
= cTD
;
2887 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2888 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2891 /* FIXME: add several sanity checks here */
2892 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2893 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2895 /* FIXME: check safearray */
2897 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2899 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2901 else if(td
[0] == VT_CARRAY
)
2903 /* array descr table here */
2904 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2906 else if(td
[0] == VT_USERDEFINED
)
2908 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2910 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2913 /* second time around to fill the array subscript info */
2916 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2917 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2919 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2920 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2923 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2925 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2927 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2929 for(j
= 0; j
<td
[2]; j
++)
2931 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2932 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2933 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2934 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2939 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2940 ERR("didn't find array description data\n");
2945 /* imported type libs */
2946 if(tlbSegDir
.pImpFiles
.offset
>0)
2948 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2949 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2952 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2956 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2957 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2958 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2960 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2961 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2962 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2963 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2966 name
= TLB_Alloc(size
+1);
2967 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2968 (*ppImpLib
)->name
= TLB_MultiByteToBSTR(name
);
2970 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2971 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2973 ppImpLib
= &(*ppImpLib
)->next
;
2977 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
2978 if(pTypeLibImpl
->dispatch_href
!= -1)
2979 MSFT_DoRefType(&cx
, pTypeLibImpl
, pTypeLibImpl
->dispatch_href
);
2982 if(tlbHeader
.nrtypeinfos
>= 0 )
2984 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2985 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2988 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
2990 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2992 ppTI
= &((*ppTI
)->next
);
2993 (pTypeLibImpl
->TypeInfoCount
)++;
2997 TRACE("(%p)\n", pTypeLibImpl
);
2998 return (ITypeLib2
*) pTypeLibImpl
;
3002 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3008 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3009 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3013 guid
->Data4
[0] = s
>> 8;
3014 guid
->Data4
[1] = s
& 0xff;
3017 for(i
= 0; i
< 6; i
++) {
3018 memcpy(b
, str
+ 24 + 2 * i
, 2);
3019 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3024 static WORD
SLTG_ReadString(const char *ptr
, BSTR
*pBstr
)
3030 bytelen
= *(const WORD
*)ptr
;
3031 if(bytelen
== 0xffff) return 2;
3032 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3033 *pBstr
= SysAllocStringLen(NULL
, len
- 1);
3035 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, *pBstr
, len
);
3039 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3044 bytelen
= *(const WORD
*)ptr
;
3045 if(bytelen
== 0xffff) return 2;
3046 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
3047 memcpy(*str
, ptr
+ 2, bytelen
);
3048 (*str
)[bytelen
] = '\0';
3052 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3054 char *ptr
= pLibBlk
;
3057 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3058 FIXME("libblk magic = %04x\n", w
);
3063 if((w
= *(WORD
*)ptr
) != 0xffff) {
3064 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3069 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
3071 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
3073 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3076 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
3079 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3080 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3082 pTypeLibImpl
->LibAttr
.lcid
= 0;
3085 ptr
+= 4; /* skip res12 */
3087 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
3090 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
3093 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
3096 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
3097 ptr
+= sizeof(GUID
);
3099 return ptr
- (char*)pLibBlk
;
3102 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3107 } sltg_ref_lookup_t
;
3109 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3110 HREFTYPE
*typelib_ref
)
3112 if(typeinfo_ref
< table
->num
)
3114 *typelib_ref
= table
->refs
[typeinfo_ref
];
3118 ERR_(typelib
)("Unable to find reference\n");
3123 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3128 if((*pType
& 0xe00) == 0xe00) {
3130 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3132 pTD
= pTD
->u
.lptdesc
;
3134 switch(*pType
& 0x3f) {
3137 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3139 pTD
= pTD
->u
.lptdesc
;
3142 case VT_USERDEFINED
:
3143 pTD
->vt
= VT_USERDEFINED
;
3144 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3150 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3153 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3155 pTD
->vt
= VT_CARRAY
;
3156 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3158 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3159 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3160 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3161 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3163 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3169 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3173 pTD
->vt
= VT_SAFEARRAY
;
3174 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3176 pTD
= pTD
->u
.lptdesc
;
3180 pTD
->vt
= *pType
& 0x3f;
3189 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3190 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3192 /* Handle [in/out] first */
3193 if((*pType
& 0xc000) == 0xc000)
3194 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3195 else if(*pType
& 0x8000)
3196 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3197 else if(*pType
& 0x4000)
3198 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3200 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3203 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3206 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3208 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3212 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3217 TLBRefType
*ref_type
;
3218 sltg_ref_lookup_t
*table
;
3219 HREFTYPE typelib_ref
;
3221 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3222 FIXME("Ref magic = %x\n", pRef
->magic
);
3225 name
= ( (char*)pRef
->names
+ pRef
->number
);
3227 table
= HeapAlloc(GetProcessHeap(), 0, sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3228 table
->num
= pRef
->number
>> 3;
3230 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3232 /* We don't want the first href to be 0 */
3233 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3235 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3237 unsigned int lib_offs
, type_num
;
3239 ref_type
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref_type
));
3241 name
+= SLTG_ReadStringA(name
, &refname
);
3242 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3243 FIXME_(typelib
)("Can't sscanf ref\n");
3244 if(lib_offs
!= 0xffff) {
3245 TLBImpLib
**import
= &pTL
->pImpLibs
;
3248 if((*import
)->offset
== lib_offs
)
3250 import
= &(*import
)->next
;
3253 char fname
[MAX_PATH
+1];
3256 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3258 (*import
)->offset
= lib_offs
;
3259 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
3261 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3262 &(*import
)->wVersionMajor
,
3263 &(*import
)->wVersionMinor
,
3264 &(*import
)->lcid
, fname
) != 4) {
3265 FIXME_(typelib
)("can't sscanf ref %s\n",
3266 pNameTable
+ lib_offs
+ 40);
3268 len
= strlen(fname
);
3269 if(fname
[len
-1] != '#')
3270 FIXME("fname = %s\n", fname
);
3271 fname
[len
-1] = '\0';
3272 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
3274 ref_type
->pImpTLInfo
= *import
;
3276 /* Store a reference to IDispatch */
3277 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&(*import
)->guid
, &IID_StdOle
) && type_num
== 4)
3278 pTL
->dispatch_href
= typelib_ref
;
3280 } else { /* internal ref */
3281 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3283 ref_type
->reference
= typelib_ref
;
3284 ref_type
->index
= type_num
;
3286 HeapFree(GetProcessHeap(), 0, refname
);
3287 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3289 table
->refs
[ref
] = typelib_ref
;
3292 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3293 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3294 dump_TLBRefType(pTL
);
3298 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3299 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3301 SLTG_ImplInfo
*info
;
3302 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
3303 /* I don't really get this structure, usually it's 0x16 bytes
3304 long, but iuser.tlb contains some that are 0x18 bytes long.
3305 That's ok because we can use the next ptr to jump to the next
3306 one. But how do we know the length of the last one? The WORD
3307 at offs 0x8 might be the clue. For now I'm just assuming that
3308 the last one is the regular 0x16 bytes. */
3310 info
= (SLTG_ImplInfo
*)pBlk
;
3312 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3313 sizeof(**ppImplType
));
3314 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &(*ppImplType
)->hRef
);
3315 (*ppImplType
)->implflags
= info
->impltypeflags
;
3316 pTI
->TypeAttr
.cImplTypes
++;
3317 ppImplType
= &(*ppImplType
)->next
;
3319 if(info
->next
== 0xffff)
3322 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3323 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3325 info
++; /* see comment at top of function */
3329 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
3330 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3332 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
3333 BSTR bstrPrevName
= NULL
;
3334 SLTG_Variable
*pItem
;
3338 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
3339 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++) {
3341 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3342 sizeof(**ppVarDesc
));
3343 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
3345 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
3346 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
3347 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
3351 if (pItem
->name
== 0xfffe)
3352 (*ppVarDesc
)->Name
= SysAllocString(bstrPrevName
);
3354 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3356 TRACE_(typelib
)("name: %s\n", debugstr_w((*ppVarDesc
)->Name
));
3357 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
3358 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
3360 if(pItem
->flags
& 0x02)
3361 pType
= &pItem
->type
;
3363 pType
= (WORD
*)(pBlk
+ pItem
->type
);
3365 if (pItem
->flags
& ~0xda)
3366 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
3368 SLTG_DoElem(pType
, pBlk
,
3369 &(*ppVarDesc
)->vardesc
.elemdescVar
, ref_lookup
);
3371 if (TRACE_ON(typelib
)) {
3373 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
3374 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
3377 if (pItem
->flags
& 0x40) {
3378 TRACE_(typelib
)("VAR_DISPATCH\n");
3379 (*ppVarDesc
)->vardesc
.varkind
= VAR_DISPATCH
;
3381 else if (pItem
->flags
& 0x10) {
3382 TRACE_(typelib
)("VAR_CONST\n");
3383 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
3384 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
3386 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
3387 if (pItem
->flags
& 0x08)
3388 V_INT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
3390 switch ((*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
)
3396 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
3398 TRACE_(typelib
)("len = %u\n", len
);
3399 if (len
== 0xffff) {
3402 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
3403 str
= SysAllocStringLen(NULL
, alloc_len
);
3404 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
3406 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_BSTR
;
3407 V_BSTR((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = str
;
3416 V_INT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) =
3417 *(INT
*)(pBlk
+ pItem
->byte_offs
);
3420 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
);
3425 TRACE_(typelib
)("VAR_PERINSTANCE\n");
3426 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
3427 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
3430 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
3431 (*ppVarDesc
)->vardesc
.wVarFlags
= pItem
->varflags
;
3433 if (pItem
->flags
& 0x80)
3434 (*ppVarDesc
)->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
3436 bstrPrevName
= (*ppVarDesc
)->Name
;
3437 ppVarDesc
= &((*ppVarDesc
)->next
);
3439 pTI
->TypeAttr
.cVars
= cVars
;
3442 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
3443 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3445 SLTG_Function
*pFunc
;
3447 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
3449 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
;
3450 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++) {
3455 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3456 sizeof(**ppFuncDesc
));
3458 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
3459 case SLTG_FUNCTION_MAGIC
:
3460 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
3462 case SLTG_DISPATCH_FUNCTION_MAGIC
:
3463 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_DISPATCH
;
3465 case SLTG_STATIC_FUNCTION_MAGIC
:
3466 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_STATIC
;
3469 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
3470 HeapFree(GetProcessHeap(), 0, *ppFuncDesc
);
3474 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
3476 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
3477 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
3478 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
3479 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
3480 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
3481 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
3483 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
3484 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
3486 if(pFunc
->retnextopt
& 0x80)
3487 pType
= &pFunc
->rettype
;
3489 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
3491 SLTG_DoElem(pType
, pBlk
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
, ref_lookup
);
3493 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
3494 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3495 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
3496 (*ppFuncDesc
)->pParamDesc
=
3497 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3498 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
3500 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
3502 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
3503 char *paramName
= pNameTable
+ *pArg
;
3505 /* If arg type follows then paramName points to the 2nd
3506 letter of the name, else the next WORD is an offset to
3507 the arg type and paramName points to the first letter.
3508 So let's take one char off paramName and see if we're
3509 pointing at an alpha-numeric char. However if *pArg is
3510 0xffff or 0xfffe then the param has no name, the former
3511 meaning that the next WORD is the type, the latter
3512 meaning that the next WORD is an offset to the type. */
3517 else if(*pArg
== 0xfffe) {
3521 else if(paramName
[-1] && !isalnum(paramName
[-1]))
3526 if(HaveOffs
) { /* the next word is an offset to type */
3527 pType
= (WORD
*)(pBlk
+ *pArg
);
3528 SLTG_DoElem(pType
, pBlk
,
3529 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3534 pArg
= SLTG_DoElem(pArg
, pBlk
,
3535 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3538 /* Are we an optional param ? */
3539 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
3540 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
3541 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
3544 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
3545 TLB_MultiByteToBSTR(paramName
);
3547 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
3548 SysAllocString((*ppFuncDesc
)->Name
);
3552 ppFuncDesc
= &((*ppFuncDesc
)->next
);
3553 if(pFunc
->next
== 0xffff) break;
3555 pTI
->TypeAttr
.cFuncs
= cFuncs
;
3558 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
3559 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3560 SLTG_TypeInfoTail
*pTITail
)
3563 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3565 if(pTIHeader
->href_table
!= 0xffffffff) {
3566 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3572 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3573 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
3575 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3579 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
3580 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3581 const SLTG_TypeInfoTail
*pTITail
)
3584 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3586 if(pTIHeader
->href_table
!= 0xffffffff) {
3587 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3593 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3594 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
3597 if (pTITail
->funcs_off
!= 0xffff)
3598 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3600 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3602 if (TRACE_ON(typelib
))
3603 dump_TLBFuncDesc(pTI
->funclist
);
3606 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
3607 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3608 const SLTG_TypeInfoTail
*pTITail
)
3610 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3613 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3614 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3615 const SLTG_TypeInfoTail
*pTITail
)
3618 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3620 if (pTITail
->simple_alias
) {
3621 /* if simple alias, no more processing required */
3622 pTI
->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3626 if(pTIHeader
->href_table
!= 0xffffffff) {
3627 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3631 /* otherwise it is an offset to a type */
3632 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
3634 SLTG_DoType(pType
, pBlk
, &pTI
->TypeAttr
.tdescAlias
, ref_lookup
);
3636 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3639 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3640 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3641 const SLTG_TypeInfoTail
*pTITail
)
3643 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3644 if (pTIHeader
->href_table
!= 0xffffffff)
3645 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3648 if (pTITail
->vars_off
!= 0xffff)
3649 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3651 if (pTITail
->funcs_off
!= 0xffff)
3652 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3654 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3655 * of dispinterface functions including the IDispatch ones, so
3656 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3657 pTI
->TypeAttr
.cbSizeVft
= pTI
->TypeAttr
.cFuncs
* sizeof(void *);
3659 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3660 if (TRACE_ON(typelib
))
3661 dump_TLBFuncDesc(pTI
->funclist
);
3664 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3665 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3666 const SLTG_TypeInfoTail
*pTITail
)
3668 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3671 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
3672 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3673 const SLTG_TypeInfoTail
*pTITail
)
3675 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3676 if (pTIHeader
->href_table
!= 0xffffffff)
3677 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3680 if (pTITail
->vars_off
!= 0xffff)
3681 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3683 if (pTITail
->funcs_off
!= 0xffff)
3684 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3685 HeapFree(GetProcessHeap(), 0, ref_lookup
);
3686 if (TRACE_ON(typelib
))
3690 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3691 managable copy of it into this */
3704 } SLTG_InternalOtherTypeInfo
;
3706 /****************************************************************************
3707 * ITypeLib2_Constructor_SLTG
3709 * loading a SLTG typelib from an in-memory image
3711 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3713 ITypeLibImpl
*pTypeLibImpl
;
3714 SLTG_Header
*pHeader
;
3715 SLTG_BlkEntry
*pBlkEntry
;
3719 LPVOID pBlk
, pFirstBlk
;
3720 SLTG_LibBlk
*pLibBlk
;
3721 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3722 char *pAfterOTIBlks
= NULL
;
3723 char *pNameTable
, *ptr
;
3726 ITypeInfoImpl
**ppTypeInfoImpl
;
3728 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3731 pTypeLibImpl
= TypeLibImpl_Constructor();
3732 if (!pTypeLibImpl
) return NULL
;
3736 TRACE_(typelib
)("header:\n");
3737 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
3738 pHeader
->nrOfFileBlks
);
3739 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3740 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
3741 pHeader
->SLTG_magic
);
3745 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3746 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3748 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3749 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3751 /* Next we have a magic block */
3752 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3754 /* Let's see if we're still in sync */
3755 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3756 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3757 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3760 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3761 sizeof(SLTG_DIR_MAGIC
))) {
3762 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
3766 pIndex
= (SLTG_Index
*)(pMagic
+1);
3768 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3770 pFirstBlk
= pPad9
+ 1;
3772 /* We'll set up a ptr to the main library block, which is the last one. */
3774 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3775 pBlkEntry
[order
].next
!= 0;
3776 order
= pBlkEntry
[order
].next
- 1, i
++) {
3777 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3781 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3783 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3788 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3790 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3791 sizeof(*pOtherTypeInfoBlks
) *
3792 pTypeLibImpl
->TypeInfoCount
);
3795 ptr
= (char*)pLibBlk
+ len
;
3797 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3801 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3803 w
= *(WORD
*)(ptr
+ 2);
3806 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3808 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3809 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3811 w
= *(WORD
*)(ptr
+ 4 + len
);
3813 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3815 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3817 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3818 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3820 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3821 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3822 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3824 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3826 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3829 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3830 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3831 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3832 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3833 len
+= sizeof(SLTG_OtherTypeInfo
);
3837 pAfterOTIBlks
= ptr
;
3839 /* Skip this WORD and get the next DWORD */
3840 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3842 /* Now add this to pLibBLk look at what we're pointing at and
3843 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3844 dust and we should be pointing at the beginning of the name
3847 pNameTable
= (char*)pLibBlk
+ len
;
3849 switch(*(WORD
*)pNameTable
) {
3856 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3860 pNameTable
+= 0x216;
3864 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3866 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3869 /* Hopefully we now have enough ptrs set up to actually read in
3870 some TypeInfos. It's not clear which order to do them in, so
3871 I'll just follow the links along the BlkEntry chain and read
3872 them in the order in which they are in the file */
3874 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3876 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3877 pBlkEntry
[order
].next
!= 0;
3878 order
= pBlkEntry
[order
].next
- 1, i
++) {
3880 SLTG_TypeInfoHeader
*pTIHeader
;
3881 SLTG_TypeInfoTail
*pTITail
;
3882 SLTG_MemberHeader
*pMemHeader
;
3884 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3885 pOtherTypeInfoBlks
[i
].index_name
)) {
3886 FIXME_(typelib
)("Index strings don't match\n");
3891 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3892 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3895 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3896 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3897 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
3899 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3900 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3901 (*ppTypeInfoImpl
)->index
= i
;
3902 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3903 pOtherTypeInfoBlks
[i
].name_offs
+
3905 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3906 (*ppTypeInfoImpl
)->TypeAttr
.guid
= pOtherTypeInfoBlks
[i
].uuid
;
3907 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3908 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3909 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3910 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3911 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3913 if((pTIHeader
->typeflags1
& 7) != 2)
3914 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3915 if(pTIHeader
->typeflags3
!= 2)
3916 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3918 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3919 debugstr_w((*ppTypeInfoImpl
)->Name
),
3920 typekind_desc
[pTIHeader
->typekind
],
3921 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3922 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3924 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
3926 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
3928 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3929 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3930 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= (pTITail
->cbSizeVft
* sizeof(void *))/4;
3932 switch(pTIHeader
->typekind
) {
3934 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3935 pTIHeader
, pTITail
);
3939 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3940 pTIHeader
, pTITail
);
3943 case TKIND_INTERFACE
:
3944 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3945 pTIHeader
, pTITail
);
3949 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3950 pTIHeader
, pTITail
);
3954 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3955 pTIHeader
, pTITail
);
3958 case TKIND_DISPATCH
:
3959 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3960 pTIHeader
, pTITail
);
3964 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3965 pTIHeader
, pTITail
);
3969 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3974 /* could get cFuncs, cVars and cImplTypes from here
3975 but we've already set those */
3976 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3991 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3992 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3995 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3996 FIXME("Somehow processed %d TypeInfos\n", i
);
4000 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
4001 return (ITypeLib2
*)pTypeLibImpl
;
4004 /* ITypeLib::QueryInterface
4006 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
4011 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4013 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4016 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4017 IsEqualIID(riid
,&IID_ITypeLib
)||
4018 IsEqualIID(riid
,&IID_ITypeLib2
))
4025 ITypeLib2_AddRef(iface
);
4026 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4029 TRACE("-- Interface: E_NOINTERFACE\n");
4030 return E_NOINTERFACE
;
4035 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4037 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4038 ULONG ref
= InterlockedIncrement(&This
->ref
);
4040 TRACE("(%p)->ref was %u\n",This
, ref
- 1);
4045 /* ITypeLib::Release
4047 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4049 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4050 ULONG ref
= InterlockedDecrement(&This
->ref
);
4052 TRACE("(%p)->(%u)\n",This
, ref
);
4056 TLBImpLib
*pImpLib
, *pImpLibNext
;
4057 TLBCustData
*pCustData
, *pCustDataNext
;
4058 TLBRefType
*ref_type
;
4062 /* remove cache entry */
4065 TRACE("removing from cache list\n");
4066 EnterCriticalSection(&cache_section
);
4067 if (This
->next
) This
->next
->prev
= This
->prev
;
4068 if (This
->prev
) This
->prev
->next
= This
->next
;
4069 else tlb_cache_first
= This
->next
;
4070 LeaveCriticalSection(&cache_section
);
4071 HeapFree(GetProcessHeap(), 0, This
->path
);
4073 TRACE(" destroying ITypeLib(%p)\n",This
);
4075 SysFreeString(This
->Name
);
4078 SysFreeString(This
->DocString
);
4079 This
->DocString
= NULL
;
4081 SysFreeString(This
->HelpFile
);
4082 This
->HelpFile
= NULL
;
4084 SysFreeString(This
->HelpStringDll
);
4085 This
->HelpStringDll
= NULL
;
4087 for (pCustData
= This
->pCustData
; pCustData
; pCustData
= pCustDataNext
)
4089 VariantClear(&pCustData
->data
);
4091 pCustDataNext
= pCustData
->next
;
4092 TLB_Free(pCustData
);
4095 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4096 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4097 TLB_Free(This
->pTypeDesc
[i
].u
.lpadesc
);
4099 TLB_Free(This
->pTypeDesc
);
4101 for (pImpLib
= This
->pImpLibs
; pImpLib
; pImpLib
= pImpLibNext
)
4103 if (pImpLib
->pImpTypeLib
)
4104 ITypeLib_Release((ITypeLib
*)pImpLib
->pImpTypeLib
);
4105 SysFreeString(pImpLib
->name
);
4107 pImpLibNext
= pImpLib
->next
;
4111 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4113 list_remove(&ref_type
->entry
);
4117 if (This
->pTypeInfo
) /* can be NULL */
4118 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
4119 HeapFree(GetProcessHeap(),0,This
);
4126 /* ITypeLib::GetTypeInfoCount
4128 * Returns the number of type descriptions in the type library
4130 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4132 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4133 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4134 return This
->TypeInfoCount
;
4137 /* ITypeLib::GetTypeInfo
4139 * retrieves the specified type description in the library.
4141 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4144 ITypeInfo
**ppTInfo
)
4148 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4149 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
4151 TRACE("(%p)->(index=%d)\n", This
, index
);
4153 if (!ppTInfo
) return E_INVALIDARG
;
4155 /* search element n in list */
4156 for(i
=0; i
< index
; i
++)
4158 pTypeInfo
= pTypeInfo
->next
;
4161 TRACE("-- element not found\n");
4162 return TYPE_E_ELEMENTNOTFOUND
;
4166 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
4168 ITypeInfo_AddRef(*ppTInfo
);
4169 TRACE("-- found (%p)\n",*ppTInfo
);
4174 /* ITypeLibs::GetTypeInfoType
4176 * Retrieves the type of a type description.
4178 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4183 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4185 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
4187 if (ITypeLib2_fnGetTypeInfoCount(iface
) < index
+ 1)
4188 return TYPE_E_ELEMENTNOTFOUND
;
4190 TRACE("(%p) index %d\n", This
, index
);
4192 if(!pTKind
) return E_INVALIDARG
;
4194 /* search element n in list */
4195 for(i
=0; i
< index
; i
++)
4199 TRACE("-- element not found\n");
4200 return TYPE_E_ELEMENTNOTFOUND
;
4202 pTInfo
= pTInfo
->next
;
4205 *pTKind
= pTInfo
->TypeAttr
.typekind
;
4206 TRACE("-- found Type (%d)\n", *pTKind
);
4210 /* ITypeLib::GetTypeInfoOfGuid
4212 * Retrieves the type description that corresponds to the specified GUID.
4215 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4218 ITypeInfo
**ppTInfo
)
4220 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4221 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
4223 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
4227 WARN("-- element not found\n");
4228 return TYPE_E_ELEMENTNOTFOUND
;
4231 /* search linked list for guid */
4232 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
4234 pTypeInfo
= pTypeInfo
->next
;
4238 /* end of list reached */
4239 WARN("-- element not found\n");
4240 return TYPE_E_ELEMENTNOTFOUND
;
4244 TRACE("-- found (%p, %s)\n",
4246 debugstr_w(pTypeInfo
->Name
));
4248 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
4249 ITypeInfo_AddRef(*ppTInfo
);
4253 /* ITypeLib::GetLibAttr
4255 * Retrieves the structure that contains the library's attributes.
4258 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4260 LPTLIBATTR
*ppTLibAttr
)
4262 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4263 TRACE("(%p)\n",This
);
4264 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
4265 **ppTLibAttr
= This
->LibAttr
;
4269 /* ITypeLib::GetTypeComp
4271 * Enables a client compiler to bind to a library's types, variables,
4272 * constants, and global functions.
4275 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4277 ITypeComp
**ppTComp
)
4279 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4281 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4282 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4283 ITypeComp_AddRef(*ppTComp
);
4288 /* ITypeLib::GetDocumentation
4290 * Retrieves the library's documentation string, the complete Help file name
4291 * and path, and the context identifier for the library Help topic in the Help
4294 * On a successful return all non-null BSTR pointers will have been set,
4297 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4301 BSTR
*pBstrDocString
,
4302 DWORD
*pdwHelpContext
,
4303 BSTR
*pBstrHelpFile
)
4305 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4307 HRESULT result
= E_INVALIDARG
;
4312 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4314 pBstrName
, pBstrDocString
,
4315 pdwHelpContext
, pBstrHelpFile
);
4319 /* documentation for the typelib */
4324 if(!(*pBstrName
= SysAllocString(This
->Name
)))
4332 if (This
->DocString
)
4334 if(!(*pBstrDocString
= SysAllocString(This
->DocString
)))
4337 else if (This
->Name
)
4339 if(!(*pBstrDocString
= SysAllocString(This
->Name
)))
4343 *pBstrDocString
= NULL
;
4347 *pdwHelpContext
= This
->dwHelpContext
;
4353 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
)))
4357 *pBstrHelpFile
= NULL
;
4364 /* for a typeinfo */
4365 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4367 if(SUCCEEDED(result
))
4369 result
= ITypeInfo_GetDocumentation(pTInfo
,
4373 pdwHelpContext
, pBstrHelpFile
);
4375 ITypeInfo_Release(pTInfo
);
4380 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
4382 if (pBstrName
) SysFreeString (*pBstrName
);
4384 return STG_E_INSUFFICIENTMEMORY
;
4389 * Indicates whether a passed-in string contains the name of a type or member
4390 * described in the library.
4393 static HRESULT WINAPI
ITypeLib2_fnIsName(
4399 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4400 ITypeInfoImpl
*pTInfo
;
4401 TLBFuncDesc
*pFInfo
;
4404 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
4406 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
4410 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
4411 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4412 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
4413 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4414 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
4415 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
4416 goto ITypeLib2_fnIsName_exit
;
4418 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
4419 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4424 ITypeLib2_fnIsName_exit
:
4425 TRACE("(%p)slow! search for %s: %s found!\n", This
,
4426 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
4431 /* ITypeLib::FindName
4433 * Finds occurrences of a type description in a type library. This may be used
4434 * to quickly verify that a name exists in a type library.
4437 static HRESULT WINAPI
ITypeLib2_fnFindName(
4441 ITypeInfo
**ppTInfo
,
4445 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4446 ITypeInfoImpl
*pTInfo
;
4447 TLBFuncDesc
*pFInfo
;
4450 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
4452 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
4453 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4454 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
4455 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4456 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++) {
4457 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
4458 goto ITypeLib2_fnFindName_exit
;
4461 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
4462 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4464 ITypeLib2_fnFindName_exit
:
4465 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
4466 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
4469 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4470 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
4477 /* ITypeLib::ReleaseTLibAttr
4479 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4482 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
4484 TLIBATTR
*pTLibAttr
)
4486 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4487 TRACE("freeing (%p)\n",This
);
4488 HeapFree(GetProcessHeap(),0,pTLibAttr
);
4492 /* ITypeLib2::GetCustData
4494 * gets the custom data
4496 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
4501 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4502 TLBCustData
*pCData
;
4504 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
4506 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4509 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4513 VariantInit( pVarVal
);
4514 VariantCopy( pVarVal
, &pCData
->data
);
4517 return E_INVALIDARG
; /* FIXME: correct? */
4520 /* ITypeLib2::GetLibStatistics
4522 * Returns statistics about a type library that are required for efficient
4523 * sizing of hash tables.
4526 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
4528 ULONG
*pcUniqueNames
,
4529 ULONG
*pcchUniqueNames
)
4531 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4533 FIXME("(%p): stub!\n", This
);
4535 if(pcUniqueNames
) *pcUniqueNames
=1;
4536 if(pcchUniqueNames
) *pcchUniqueNames
=1;
4540 /* ITypeLib2::GetDocumentation2
4542 * Retrieves the library's documentation string, the complete Help file name
4543 * and path, the localization context to use, and the context ID for the
4544 * library Help topic in the Help file.
4547 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
4551 BSTR
*pbstrHelpString
,
4552 DWORD
*pdwHelpStringContext
,
4553 BSTR
*pbstrHelpStringDll
)
4555 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4559 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
4561 /* the help string should be obtained from the helpstringdll,
4562 * using the _DLLGetDocumentation function, based on the supplied
4563 * lcid. Nice to do sometime...
4567 /* documentation for the typelib */
4569 *pbstrHelpString
=SysAllocString(This
->DocString
);
4570 if(pdwHelpStringContext
)
4571 *pdwHelpStringContext
=This
->dwHelpContext
;
4572 if(pbstrHelpStringDll
)
4573 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
4579 /* for a typeinfo */
4580 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
4582 if(SUCCEEDED(result
))
4584 ITypeInfo2
* pTInfo2
;
4585 result
= ITypeInfo_QueryInterface(pTInfo
,
4587 (LPVOID
*) &pTInfo2
);
4589 if(SUCCEEDED(result
))
4591 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
4595 pdwHelpStringContext
,
4596 pbstrHelpStringDll
);
4598 ITypeInfo2_Release(pTInfo2
);
4601 ITypeInfo_Release(pTInfo
);
4607 /* ITypeLib2::GetAllCustData
4609 * Gets all custom data items for the library.
4612 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
4614 CUSTDATA
*pCustData
)
4616 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4617 TLBCustData
*pCData
;
4619 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
4620 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
4621 if(pCustData
->prgCustData
){
4622 pCustData
->cCustData
=This
->ctCustData
;
4623 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
4624 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4625 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
4628 ERR(" OUT OF MEMORY!\n");
4629 return E_OUTOFMEMORY
;
4634 static const ITypeLib2Vtbl tlbvt
= {
4635 ITypeLib2_fnQueryInterface
,
4637 ITypeLib2_fnRelease
,
4638 ITypeLib2_fnGetTypeInfoCount
,
4639 ITypeLib2_fnGetTypeInfo
,
4640 ITypeLib2_fnGetTypeInfoType
,
4641 ITypeLib2_fnGetTypeInfoOfGuid
,
4642 ITypeLib2_fnGetLibAttr
,
4643 ITypeLib2_fnGetTypeComp
,
4644 ITypeLib2_fnGetDocumentation
,
4646 ITypeLib2_fnFindName
,
4647 ITypeLib2_fnReleaseTLibAttr
,
4649 ITypeLib2_fnGetCustData
,
4650 ITypeLib2_fnGetLibStatistics
,
4651 ITypeLib2_fnGetDocumentation2
,
4652 ITypeLib2_fnGetAllCustData
4656 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4658 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4660 return ITypeLib2_QueryInterface((ITypeLib
*)This
, riid
, ppv
);
4663 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4665 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4667 return ITypeLib2_AddRef((ITypeLib2
*)This
);
4670 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4672 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4674 return ITypeLib2_Release((ITypeLib2
*)This
);
4677 static HRESULT WINAPI
ITypeLibComp_fnBind(
4682 ITypeInfo
** ppTInfo
,
4683 DESCKIND
* pDescKind
,
4686 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4687 ITypeInfoImpl
*pTypeInfo
;
4689 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4691 *pDescKind
= DESCKIND_NONE
;
4692 pBindPtr
->lptcomp
= NULL
;
4695 for (pTypeInfo
= This
->pTypeInfo
; pTypeInfo
; pTypeInfo
= pTypeInfo
->next
)
4697 TRACE("testing %s\n", debugstr_w(pTypeInfo
->Name
));
4699 /* FIXME: check wFlags here? */
4700 /* FIXME: we should use a hash table to look this info up using lHash
4701 * instead of an O(n) search */
4702 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
) ||
4703 (pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
))
4705 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
, szName
))
4707 *pDescKind
= DESCKIND_TYPECOMP
;
4708 pBindPtr
->lptcomp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4709 ITypeComp_AddRef(pBindPtr
->lptcomp
);
4710 TRACE("module or enum: %s\n", debugstr_w(szName
));
4715 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
) ||
4716 (pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
))
4718 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4721 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4722 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
4724 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
4729 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_COCLASS
) &&
4730 (pTypeInfo
->TypeAttr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
4732 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4734 ITypeInfo
*subtypeinfo
;
4736 DESCKIND subdesckind
;
4738 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
4739 &subtypeinfo
, &subdesckind
, &subbindptr
);
4740 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
4742 TYPEDESC tdesc_appobject
=
4745 (TYPEDESC
*)pTypeInfo
->hreftype
4749 const VARDESC vardesc_appobject
=
4752 NULL
, /* lpstrSchema */
4767 VAR_STATIC
/* varkind */
4770 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
4772 /* cleanup things filled in by Bind call so we can put our
4773 * application object data in there instead */
4774 switch (subdesckind
)
4776 case DESCKIND_FUNCDESC
:
4777 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
4779 case DESCKIND_VARDESC
:
4780 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
4785 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
4787 if (pTypeInfo
->hreftype
== -1)
4788 FIXME("no hreftype for interface %p\n", pTypeInfo
);
4790 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
4794 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
4795 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
4796 ITypeInfo_AddRef(*ppTInfo
);
4802 TRACE("name not found %s\n", debugstr_w(szName
));
4806 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4810 ITypeInfo
** ppTInfo
,
4811 ITypeComp
** ppTComp
)
4813 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4817 static const ITypeCompVtbl tlbtcvt
=
4820 ITypeLibComp_fnQueryInterface
,
4821 ITypeLibComp_fnAddRef
,
4822 ITypeLibComp_fnRelease
,
4824 ITypeLibComp_fnBind
,
4825 ITypeLibComp_fnBindType
4828 /*================== ITypeInfo(2) Methods ===================================*/
4829 static ITypeInfo2
* ITypeInfo_Constructor(void)
4831 ITypeInfoImpl
* pTypeInfoImpl
;
4833 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4836 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4837 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4838 pTypeInfoImpl
->ref
=1;
4839 pTypeInfoImpl
->hreftype
= -1;
4840 pTypeInfoImpl
->TypeAttr
.memidConstructor
= MEMBERID_NIL
;
4841 pTypeInfoImpl
->TypeAttr
.memidDestructor
= MEMBERID_NIL
;
4843 TRACE("(%p)\n", pTypeInfoImpl
);
4844 return (ITypeInfo2
*) pTypeInfoImpl
;
4847 /* ITypeInfo::QueryInterface
4849 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4854 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4856 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4859 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4860 IsEqualIID(riid
,&IID_ITypeInfo
)||
4861 IsEqualIID(riid
,&IID_ITypeInfo2
))
4865 ITypeInfo_AddRef(iface
);
4866 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4869 TRACE("-- Interface: E_NOINTERFACE\n");
4870 return E_NOINTERFACE
;
4873 /* ITypeInfo::AddRef
4875 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4877 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4878 ULONG ref
= InterlockedIncrement(&This
->ref
);
4880 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4882 TRACE("(%p)->ref is %u\n",This
, ref
);
4886 /* ITypeInfo::Release
4888 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
4890 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4891 ULONG ref
= InterlockedDecrement(&This
->ref
);
4893 TRACE("(%p)->(%u)\n",This
, ref
);
4896 /* We don't release ITypeLib when ref=0 because
4897 it means that function is called by ITypeLib2_Release */
4898 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
4900 TLBFuncDesc
*pFInfo
, *pFInfoNext
;
4901 TLBVarDesc
*pVInfo
, *pVInfoNext
;
4902 TLBImplType
*pImpl
, *pImplNext
;
4904 TRACE("destroying ITypeInfo(%p)\n",This
);
4906 if (This
->no_free_data
)
4909 SysFreeString(This
->Name
);
4912 SysFreeString(This
->DocString
);
4913 This
->DocString
= NULL
;
4915 SysFreeString(This
->DllName
);
4916 This
->DllName
= NULL
;
4918 for (pFInfo
= This
->funclist
; pFInfo
; pFInfo
= pFInfoNext
)
4921 for(i
= 0;i
< pFInfo
->funcdesc
.cParams
; i
++)
4923 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[i
];
4924 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4926 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
4927 TLB_Free(elemdesc
->u
.paramdesc
.pparamdescex
);
4929 SysFreeString(pFInfo
->pParamDesc
[i
].Name
);
4931 TLB_Free(pFInfo
->funcdesc
.lprgelemdescParam
);
4932 TLB_Free(pFInfo
->pParamDesc
);
4933 TLB_FreeCustData(pFInfo
->pCustData
);
4934 if (HIWORD(pFInfo
->Entry
) != 0 && pFInfo
->Entry
!= (BSTR
)-1)
4935 SysFreeString(pFInfo
->Entry
);
4936 SysFreeString(pFInfo
->HelpString
);
4937 SysFreeString(pFInfo
->Name
);
4939 pFInfoNext
= pFInfo
->next
;
4942 for (pVInfo
= This
->varlist
; pVInfo
; pVInfo
= pVInfoNext
)
4944 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
4946 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
4947 TLB_Free(pVInfo
->vardesc
.u
.lpvarValue
);
4949 TLB_FreeCustData(pVInfo
->pCustData
);
4950 SysFreeString(pVInfo
->Name
);
4951 pVInfoNext
= pVInfo
->next
;
4954 for(pImpl
= This
->impltypelist
; pImpl
; pImpl
= pImplNext
)
4956 TLB_FreeCustData(pImpl
->pCustData
);
4957 pImplNext
= pImpl
->next
;
4960 TLB_FreeCustData(This
->pCustData
);
4965 ITypeInfo_Release((ITypeInfo
*)This
->next
);
4968 HeapFree(GetProcessHeap(),0,This
);
4974 /* ITypeInfo::GetTypeAttr
4976 * Retrieves a TYPEATTR structure that contains the attributes of the type
4980 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
4981 LPTYPEATTR
*ppTypeAttr
)
4983 const ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4986 TRACE("(%p)\n",This
);
4988 size
= sizeof(**ppTypeAttr
);
4989 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
4990 size
+= TLB_SizeTypeDesc(&This
->TypeAttr
.tdescAlias
, FALSE
);
4992 *ppTypeAttr
= HeapAlloc(GetProcessHeap(), 0, size
);
4994 return E_OUTOFMEMORY
;
4996 **ppTypeAttr
= This
->TypeAttr
;
4998 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
4999 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5000 &This
->TypeAttr
.tdescAlias
, *ppTypeAttr
+ 1);
5002 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5003 /* This should include all the inherited funcs */
5004 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ sizeof(void *);
5005 (*ppTypeAttr
)->cbSizeVft
= 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5006 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5011 /* ITypeInfo::GetTypeComp
5013 * Retrieves the ITypeComp interface for the type description, which enables a
5014 * client compiler to bind to the type description's members.
5017 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5018 ITypeComp
* *ppTComp
)
5020 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5022 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5024 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
5025 ITypeComp_AddRef(*ppTComp
);
5029 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5031 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5032 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5033 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5037 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5040 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5041 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5043 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5044 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5045 *buffer
+= sizeof(PARAMDESCEX
);
5046 *pparamdescex_dest
= *pparamdescex_src
;
5047 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5048 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5049 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5052 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5056 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5058 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5059 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5062 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5066 SIZE_T size
= sizeof(*src
);
5070 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5071 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5072 for (i
= 0; i
< src
->cParams
; i
++)
5074 size
+= sizeof(ELEMDESC
);
5075 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5078 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5079 if (!dest
) return E_OUTOFMEMORY
;
5082 if (dispinterface
) /* overwrite funckind */
5083 dest
->funckind
= FUNC_DISPATCH
;
5084 buffer
= (char *)(dest
+ 1);
5086 dest
->lprgscode
= (SCODE
*)buffer
;
5087 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5088 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5090 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5093 SysFreeString((BSTR
)dest
);
5097 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5098 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5099 for (i
= 0; i
< src
->cParams
; i
++)
5101 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5107 /* undo the above actions */
5108 for (i
= i
- 1; i
>= 0; i
--)
5109 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5110 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5111 SysFreeString((BSTR
)dest
);
5115 /* special treatment for dispinterfaces: this makes functions appear
5116 * to return their [retval] value when it is really returning an
5118 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5120 if (dest
->cParams
&&
5121 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5123 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5124 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5126 ERR("elemdesc should have started with VT_PTR instead of:\n");
5128 dump_ELEMDESC(elemdesc
);
5129 return E_UNEXPECTED
;
5132 /* copy last parameter to the return value. we are using a flat
5133 * buffer so there is no danger of leaking memory in
5135 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5137 /* remove the last parameter */
5141 /* otherwise this function is made to appear to have no return
5143 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5151 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5153 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5154 const TLBFuncDesc
*pFDesc
;
5157 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
5162 *ppFuncDesc
= &pFDesc
->funcdesc
;
5166 return TYPE_E_ELEMENTNOTFOUND
;
5169 /* internal function to make the inherited interfaces' methods appear
5170 * part of the interface */
5171 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5172 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5174 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5176 UINT implemented_funcs
= 0;
5181 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5183 if(This
->impltypelist
)
5185 ITypeInfo
*pSubTypeInfo
;
5188 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pSubTypeInfo
);
5192 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5195 &sub_funcs
, hrefoffset
);
5196 implemented_funcs
+= sub_funcs
;
5197 ITypeInfo_Release(pSubTypeInfo
);
5200 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5204 *funcs
= implemented_funcs
+ This
->TypeAttr
.cFuncs
;
5208 if (index
< implemented_funcs
)
5209 return E_INVALIDARG
;
5210 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5214 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5216 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5219 switch (pTypeDesc
->vt
)
5221 case VT_USERDEFINED
:
5222 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5226 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5229 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5237 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5240 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5241 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5242 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5245 /* ITypeInfo::GetFuncDesc
5247 * Retrieves the FUNCDESC structure that contains information about a
5248 * specified function.
5251 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5252 LPFUNCDESC
*ppFuncDesc
)
5254 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5255 const FUNCDESC
*internal_funcdesc
;
5257 UINT hrefoffset
= 0;
5259 TRACE("(%p) index %d\n", This
, index
);
5261 if (This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5262 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5263 &internal_funcdesc
, NULL
,
5266 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5267 &internal_funcdesc
);
5270 WARN("description for function %d not found\n", index
);
5274 hr
= TLB_AllocAndInitFuncDesc(
5277 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
5279 if ((This
->TypeAttr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
5280 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5282 TRACE("-- 0x%08x\n", hr
);
5286 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5290 SIZE_T size
= sizeof(*src
);
5293 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
5294 if (src
->varkind
== VAR_CONST
)
5295 size
+= sizeof(VARIANT
);
5296 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
5298 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
5299 if (!dest
) return E_OUTOFMEMORY
;
5302 buffer
= (char *)(dest
+ 1);
5303 if (src
->lpstrSchema
)
5306 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
5307 len
= strlenW(src
->lpstrSchema
);
5308 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
5309 buffer
+= (len
+ 1) * sizeof(WCHAR
);
5312 if (src
->varkind
== VAR_CONST
)
5316 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
5317 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
5318 buffer
+= sizeof(VARIANT
);
5319 VariantInit(dest
->u
.lpvarValue
);
5320 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
5323 SysFreeString((BSTR
)dest_ptr
);
5327 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
5330 if (src
->varkind
== VAR_CONST
)
5331 VariantClear(dest
->u
.lpvarValue
);
5332 SysFreeString((BSTR
)dest
);
5339 /* ITypeInfo::GetVarDesc
5341 * Retrieves a VARDESC structure that describes the specified variable.
5344 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
5345 LPVARDESC
*ppVarDesc
)
5347 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5349 const TLBVarDesc
*pVDesc
;
5351 TRACE("(%p) index %d\n", This
, index
);
5353 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
5357 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
5359 return E_INVALIDARG
;
5362 /* ITypeInfo_GetNames
5364 * Retrieves the variable with the specified member ID (or the name of the
5365 * property or method and its parameters) that correspond to the specified
5368 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
5369 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
5371 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5372 const TLBFuncDesc
*pFDesc
;
5373 const TLBVarDesc
*pVDesc
;
5375 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
5376 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
5379 /* function found, now return function and parameter names */
5380 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
5383 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
5385 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
5391 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
5394 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
5399 if(This
->impltypelist
&&
5400 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
5401 /* recursive search */
5404 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
5406 if(SUCCEEDED(result
))
5408 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
5409 ITypeInfo_Release(pTInfo
);
5412 WARN("Could not search inherited interface!\n");
5416 WARN("no names found\n");
5419 return TYPE_E_ELEMENTNOTFOUND
;
5426 /* ITypeInfo::GetRefTypeOfImplType
5428 * If a type description describes a COM class, it retrieves the type
5429 * description of the implemented interface types. For an interface,
5430 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5434 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
5439 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5442 const TLBImplType
*pImpl
= This
->impltypelist
;
5444 TRACE("(%p) index %d\n", This
, index
);
5445 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
5449 /* only valid on dual interfaces;
5450 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5452 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
5454 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
5455 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
5461 hr
= TYPE_E_ELEMENTNOTFOUND
;
5464 else if(index
== 0 && This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5466 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5467 *pRefType
= This
->pTypeLib
->dispatch_href
;
5471 /* get element n from linked list */
5472 for(i
=0; pImpl
&& i
<index
; i
++)
5474 pImpl
= pImpl
->next
;
5478 *pRefType
= pImpl
->hRef
;
5480 hr
= TYPE_E_ELEMENTNOTFOUND
;
5486 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
5488 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
5494 /* ITypeInfo::GetImplTypeFlags
5496 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5497 * or base interface in a type description.
5499 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
5500 UINT index
, INT
*pImplTypeFlags
)
5502 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5506 TRACE("(%p) index %d\n", This
, index
);
5507 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
5508 i
++, pImpl
=pImpl
->next
)
5510 if(i
==index
&& pImpl
){
5511 *pImplTypeFlags
=pImpl
->implflags
;
5515 return TYPE_E_ELEMENTNOTFOUND
;
5519 * Maps between member names and member IDs, and parameter names and
5522 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
5523 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
5525 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5526 const TLBFuncDesc
*pFDesc
;
5527 const TLBVarDesc
*pVDesc
;
5531 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
5534 /* init out parameters in case of failure */
5535 for (i
= 0; i
< cNames
; i
++)
5536 pMemId
[i
] = MEMBERID_NIL
;
5538 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
5540 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
5541 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
5542 for(i
=1; i
< cNames
; i
++){
5543 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
5544 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
5546 if( j
<pFDesc
->funcdesc
.cParams
)
5549 ret
=DISP_E_UNKNOWNNAME
;
5551 TRACE("-- 0x%08x\n", ret
);
5555 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
5556 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
5557 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
5561 /* not found, see if it can be found in an inherited interface */
5562 if(This
->impltypelist
) {
5563 /* recursive search */
5565 ret
=ITypeInfo_GetRefTypeInfo(iface
,
5566 This
->impltypelist
->hRef
, &pTInfo
);
5568 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
5569 ITypeInfo_Release(pTInfo
);
5572 WARN("Could not search inherited interface!\n");
5574 WARN("no names found\n");
5575 return DISP_E_UNKNOWNNAME
;
5578 /* ITypeInfo::Invoke
5580 * Invokes a method, or accesses a property of an object, that implements the
5581 * interface described by the type description.
5584 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
5587 if (TRACE_ON(ole
)) {
5589 TRACE("Calling %p(",func
);
5590 for (i
=0;i
<nrargs
;i
++) TRACE("%08x,",args
[i
]);
5602 res
= func(args
[0]);
5605 res
= func(args
[0],args
[1]);
5608 res
= func(args
[0],args
[1],args
[2]);
5611 res
= func(args
[0],args
[1],args
[2],args
[3]);
5614 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
5617 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
5620 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
5623 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
5626 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
5629 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9]);
5632 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10]);
5635 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]);
5638 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]);
5641 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]);
5644 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]);
5647 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]);
5650 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]);
5653 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]);
5656 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]);
5659 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]);
5662 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]);
5665 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]);
5668 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]);
5671 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]);
5674 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]);
5677 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]);
5680 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]);
5683 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]);
5686 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]);
5689 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]);
5692 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
5698 FIXME("unsupported calling convention %d\n",callconv
);
5702 TRACE("returns %08x\n",res
);
5706 /* The size of the argument on the stack in DWORD units (in all x86 call
5707 * convetions the arguments on the stack are DWORD-aligned)
5709 static int _dispargsize(VARTYPE vt
)
5714 return 8/sizeof(DWORD
);
5716 return sizeof(double)/sizeof(DWORD
);
5718 return (sizeof(DECIMAL
)+3)/sizeof(DWORD
);
5720 return sizeof(CY
)/sizeof(DWORD
);
5722 return sizeof(DATE
)/sizeof(DWORD
);
5724 return (sizeof(VARIANT
)+3)/sizeof(DWORD
);
5726 FIXME("VT_RECORD not implemented\n");
5733 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5736 ITypeInfo
*tinfo2
= NULL
;
5737 TYPEATTR
*tattr
= NULL
;
5739 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
5742 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5744 tdesc
->u
.hreftype
, hr
);
5747 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
5750 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
5751 ITypeInfo_Release(tinfo2
);
5755 switch (tattr
->typekind
)
5762 tdesc
= &tattr
->tdescAlias
;
5763 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
5766 case TKIND_INTERFACE
:
5767 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
5773 case TKIND_DISPATCH
:
5782 FIXME("TKIND_RECORD unhandled.\n");
5787 FIXME("TKIND_UNION unhandled.\n");
5792 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
5796 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
5797 ITypeInfo_Release(tinfo2
);
5801 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5805 /* enforce only one level of pointer indirection */
5806 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
5808 tdesc
= tdesc
->u
.lptdesc
;
5810 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5811 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5812 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5813 if ((tdesc
->vt
== VT_USERDEFINED
) ||
5814 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
5816 VARTYPE vt_userdefined
= 0;
5817 const TYPEDESC
*tdesc_userdefined
= tdesc
;
5818 if (tdesc
->vt
== VT_PTR
)
5820 vt_userdefined
= VT_BYREF
;
5821 tdesc_userdefined
= tdesc
->u
.lptdesc
;
5823 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
5825 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
5826 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
5828 *vt
|= vt_userdefined
;
5840 case VT_USERDEFINED
:
5841 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
5848 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
5849 hr
= DISP_E_BADVARTYPE
;
5853 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
5862 /***********************************************************************
5863 * DispCallFunc (OLEAUT32.@)
5865 * Invokes a function of the specified calling convention, passing the
5866 * specified arguments and returns the result.
5869 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5870 * oVft [I] The offset in the vtable. See notes.
5871 * cc [I] Calling convention of the function to call.
5872 * vtReturn [I] The return type of the function.
5873 * cActuals [I] Number of parameters.
5874 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5875 * prgpvarg [I] The arguments to pass.
5876 * pvargResult [O] The return value of the function. Can be NULL.
5880 * Failure: HRESULT code.
5883 * The HRESULT return value of this function is not affected by the return
5884 * value of the user supplied function, which is returned in pvargResult.
5886 * If pvInstance is NULL then a non-object function is to be called and oVft
5887 * is the address of the function to call.
5889 * The cc parameter can be one of the following values:
5902 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
5903 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
5905 int argsize
, argspos
;
5910 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5911 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
5912 pvargResult
, V_VT(pvargResult
));
5916 argsize
++; /* for This pointer */
5918 for (i
=0;i
<cActuals
;i
++)
5920 TRACE("arg %u: type %d, size %d\n",i
,prgvt
[i
],_dispargsize(prgvt
[i
]));
5921 dump_Variant(prgpvarg
[i
]);
5922 argsize
+= _dispargsize(prgvt
[i
]);
5924 args
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
5929 args
[0] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
5933 for (i
=0;i
<cActuals
;i
++)
5935 VARIANT
*arg
= prgpvarg
[i
];
5936 TRACE("Storing arg %u (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
5937 if (prgvt
[i
] == VT_VARIANT
)
5938 memcpy(&args
[argspos
], arg
, _dispargsize(prgvt
[i
]) * sizeof(DWORD
));
5940 memcpy(&args
[argspos
], &V_NONE(arg
), _dispargsize(prgvt
[i
]) * sizeof(DWORD
));
5941 argspos
+= _dispargsize(prgvt
[i
]);
5946 FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
5947 hres
= _invoke(vtable
[oVft
/sizeof(void *)], cc
, argsize
, args
);
5950 /* if we aren't invoking an object then the function pointer is stored
5952 hres
= _invoke((FARPROC
)oVft
, cc
, argsize
, args
);
5954 if (pvargResult
&& (vtReturn
!= VT_EMPTY
))
5956 TRACE("Method returned 0x%08x\n",hres
);
5957 V_VT(pvargResult
) = vtReturn
;
5958 V_UI4(pvargResult
) = hres
;
5961 HeapFree(GetProcessHeap(),0,args
);
5965 #define INVBUF_ELEMENT_SIZE \
5966 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5967 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5968 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5969 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5970 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5971 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5972 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5973 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5975 static HRESULT WINAPI
ITypeInfo_fnInvoke(
5980 DISPPARAMS
*pDispParams
,
5981 VARIANT
*pVarResult
,
5982 EXCEPINFO
*pExcepInfo
,
5985 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5987 unsigned int var_index
;
5990 const TLBFuncDesc
*pFuncInfo
;
5992 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5993 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
5998 ERR("NULL pDispParams not allowed\n");
5999 return E_INVALIDARG
;
6002 dump_DispParms(pDispParams
);
6004 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6006 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6007 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6008 return E_INVALIDARG
;
6011 /* we do this instead of using GetFuncDesc since it will return a fake
6012 * FUNCDESC for dispinterfaces and we want the real function description */
6013 for (pFuncInfo
= This
->funclist
; pFuncInfo
; pFuncInfo
=pFuncInfo
->next
)
6014 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6015 (wFlags
& pFuncInfo
->funcdesc
.invkind
))
6019 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6023 TRACE("invoking:\n");
6024 dump_TLBFuncDescOne(pFuncInfo
);
6027 switch (func_desc
->funckind
) {
6028 case FUNC_PUREVIRTUAL
:
6029 case FUNC_VIRTUAL
: {
6030 void *buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6032 VARIANT retval
; /* pointer for storing byref retvals in */
6033 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6034 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6035 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6036 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6037 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6041 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6043 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6045 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6046 hres
= DISP_E_PARAMNOTFOUND
;
6049 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6051 rgdispidNamedArgs
++;
6054 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6056 ERR("functions with the vararg attribute do not support named arguments\n");
6057 hres
= DISP_E_NONAMEDARGS
;
6061 for (i
= 0; i
< func_desc
->cParams
; i
++)
6063 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6064 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6069 TRACE("changing args\n");
6070 for (i
= 0; i
< func_desc
->cParams
; i
++)
6072 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6073 VARIANTARG
*src_arg
;
6079 for (j
= 0; j
< cNamedArgs
; j
++)
6080 if (rgdispidNamedArgs
[j
] == i
)
6082 src_arg
= &pDispParams
->rgvarg
[j
];
6087 src_arg
= i
< pDispParams
->cArgs
? &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
] : NULL
;
6089 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6091 /* under most conditions the caller is not allowed to
6092 * pass in a dispparam arg in the index of what would be
6093 * the retval parameter. however, there is an exception
6094 * where the extra parameter is used in an extra
6095 * IDispatch::Invoke below */
6096 if ((i
< pDispParams
->cArgs
) &&
6097 ((func_desc
->cParams
!= 1) || !pVarResult
||
6098 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
6100 hres
= DISP_E_BADPARAMCOUNT
;
6104 /* note: this check is placed so that if the caller passes
6105 * in a VARIANTARG for the retval we just ignore it, like
6107 if (i
== func_desc
->cParams
- 1)
6110 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6111 memset(arg
, 0, sizeof(*arg
));
6112 V_VT(arg
) = rgvt
[i
];
6113 memset(&retval
, 0, sizeof(retval
));
6114 V_BYREF(arg
) = &retval
;
6118 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
6119 hres
= E_UNEXPECTED
;
6125 dump_Variant(src_arg
);
6127 if (rgvt
[i
] == VT_VARIANT
)
6128 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
6129 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
6131 if (rgvt
[i
] == V_VT(src_arg
))
6132 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
6135 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6136 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
6137 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
6139 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6141 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
6144 SAFEARRAYBOUND bound
;
6148 bound
.cElements
= pDispParams
->cArgs
-i
;
6149 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
6151 ERR("SafeArrayCreate failed\n");
6154 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6157 ERR("SafeArrayAccessData failed with %x\n", hres
);
6160 for (j
= 0; j
< bound
.cElements
; j
++)
6161 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
6162 hres
= SafeArrayUnaccessData(a
);
6165 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6168 V_ARRAY(&rgvarg
[i
]) = a
;
6169 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6171 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
6173 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6174 V_VT(&missing_arg
[i
]) = V_VT(src_arg
);
6175 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
6176 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
6177 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6179 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
6181 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
6182 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6186 /* FIXME: this doesn't work for VT_BYREF arguments if
6187 * they are not the same type as in the paramdesc */
6188 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
6189 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
6190 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6195 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
6196 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
6197 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
6200 prgpvarg
[i
] = &rgvarg
[i
];
6202 else if (wParamFlags
& PARAMFLAG_FOPT
)
6205 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6206 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6208 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
6214 VARIANTARG
*missing_arg
;
6215 /* if the function wants a pointer to a variant then
6216 * set that up, otherwise just pass the VT_ERROR in
6217 * the argument by value */
6218 if (rgvt
[i
] & VT_BYREF
)
6220 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
6221 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
6222 V_VARIANTREF(arg
) = missing_arg
;
6226 V_VT(missing_arg
) = VT_ERROR
;
6227 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
6232 hres
= DISP_E_BADPARAMCOUNT
;
6236 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6238 /* VT_VOID is a special case for return types, so it is not
6239 * handled in the general function */
6240 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
6241 V_VT(&varresult
) = VT_EMPTY
;
6244 V_VT(&varresult
) = 0;
6245 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
6246 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6249 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
, func_desc
->callconv
,
6250 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
6251 prgpvarg
, &varresult
);
6253 for (i
= 0; i
< func_desc
->cParams
; i
++)
6255 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6256 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6260 TRACE("[retval] value: ");
6261 dump_Variant(prgpvarg
[i
]);
6266 VariantInit(pVarResult
);
6267 /* deref return value */
6268 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
6271 /* free data stored in varresult. Note that
6272 * VariantClear doesn't do what we want because we are
6273 * working with byref types. */
6274 /* FIXME: clear safearrays, bstrs, records and
6275 * variants here too */
6276 if ((V_VT(prgpvarg
[i
]) == (VT_UNKNOWN
| VT_BYREF
)) ||
6277 (V_VT(prgpvarg
[i
]) == (VT_DISPATCH
| VT_BYREF
)))
6279 if(*V_UNKNOWNREF(prgpvarg
[i
]))
6280 IUnknown_Release(*V_UNKNOWNREF(prgpvarg
[i
]));
6284 else if (i
< pDispParams
->cArgs
)
6286 if (wParamFlags
& PARAMFLAG_FOUT
)
6288 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
];
6290 if ((rgvt
[i
] == VT_BYREF
) && (V_VT(arg
) != VT_BYREF
))
6291 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
6295 ERR("failed to convert param %d to vt %d\n", i
,
6296 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
]));
6300 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
6301 func_desc
->cParamsOpt
< 0 &&
6302 i
== func_desc
->cParams
-1)
6304 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
6307 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
6310 ERR("SafeArrayGetUBound failed with %x\n", hres
);
6313 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6316 ERR("SafeArrayAccessData failed with %x\n", hres
);
6319 for (j
= 0; j
<= ubound
; j
++)
6320 VariantClear(&v
[j
]);
6321 hres
= SafeArrayUnaccessData(a
);
6324 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6328 VariantClear(&rgvarg
[i
]);
6330 else if (wParamFlags
& PARAMFLAG_FOPT
)
6332 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6333 VariantClear(&rgvarg
[i
]);
6337 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
6339 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
6340 hres
= DISP_E_EXCEPTION
;
6343 IErrorInfo
*pErrorInfo
;
6344 pExcepInfo
->scode
= V_ERROR(&varresult
);
6345 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
6347 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
6348 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
6349 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
6350 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
6352 IErrorInfo_Release(pErrorInfo
);
6356 if (V_VT(&varresult
) != VT_ERROR
)
6358 TRACE("varresult value: ");
6359 dump_Variant(&varresult
);
6363 VariantClear(pVarResult
);
6364 *pVarResult
= varresult
;
6367 VariantClear(&varresult
);
6370 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
6371 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
6372 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
6373 (pDispParams
->cArgs
!= 0))
6375 if (V_VT(pVarResult
) == VT_DISPATCH
)
6377 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
6378 /* Note: not VariantClear; we still need the dispatch
6379 * pointer to be valid */
6380 VariantInit(pVarResult
);
6381 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
6382 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
6383 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
6384 IDispatch_Release(pDispatch
);
6388 VariantClear(pVarResult
);
6389 hres
= DISP_E_NOTACOLLECTION
;
6394 HeapFree(GetProcessHeap(), 0, buffer
);
6397 case FUNC_DISPATCH
: {
6400 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
6401 if (SUCCEEDED(hres
)) {
6402 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6403 hres
= IDispatch_Invoke(
6404 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
6405 pVarResult
,pExcepInfo
,pArgErr
6408 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
6409 IDispatch_Release(disp
);
6411 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6415 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
6420 TRACE("-- 0x%08x\n", hres
);
6423 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
6426 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
6427 if(FAILED(hres
)) return hres
;
6429 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6430 dump_VARDESC(var_desc
);
6431 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
6435 /* not found, look for it in inherited interfaces */
6436 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
6437 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
6438 if(This
->impltypelist
) {
6439 /* recursive search */
6441 hres
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pTInfo
);
6442 if(SUCCEEDED(hres
)){
6443 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
6444 ITypeInfo_Release(pTInfo
);
6447 WARN("Could not search inherited interface!\n");
6450 ERR("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
6451 return DISP_E_MEMBERNOTFOUND
;
6454 /* ITypeInfo::GetDocumentation
6456 * Retrieves the documentation string, the complete Help file name and path,
6457 * and the context ID for the Help topic for a specified type description.
6459 * (Can be tested by the Visual Basic Editor in Word for instance.)
6461 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
6462 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
6463 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
6465 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6466 const TLBFuncDesc
*pFDesc
;
6467 const TLBVarDesc
*pVDesc
;
6468 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6469 " HelpContext(%p) HelpFile(%p)\n",
6470 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6471 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
6473 *pBstrName
=SysAllocString(This
->Name
);
6475 *pBstrDocString
=SysAllocString(This
->DocString
);
6477 *pdwHelpContext
=This
->dwHelpContext
;
6479 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
6481 }else {/* for a member */
6482 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6483 if(pFDesc
->funcdesc
.memid
==memid
){
6485 *pBstrName
= SysAllocString(pFDesc
->Name
);
6487 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
6489 *pdwHelpContext
=pFDesc
->helpcontext
;
6492 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
6493 if(pVDesc
->vardesc
.memid
==memid
){
6495 *pBstrName
= SysAllocString(pVDesc
->Name
);
6497 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
6499 *pdwHelpContext
=pVDesc
->HelpContext
;
6504 if(This
->impltypelist
&&
6505 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
6506 /* recursive search */
6509 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
6511 if(SUCCEEDED(result
)) {
6512 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
6513 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6514 ITypeInfo_Release(pTInfo
);
6517 WARN("Could not search inherited interface!\n");
6520 WARN("member %d not found\n", memid
);
6521 return TYPE_E_ELEMENTNOTFOUND
;
6524 /* ITypeInfo::GetDllEntry
6526 * Retrieves a description or specification of an entry point for a function
6529 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
6530 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
6533 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6534 const TLBFuncDesc
*pFDesc
;
6536 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
6538 if (pBstrDllName
) *pBstrDllName
= NULL
;
6539 if (pBstrName
) *pBstrName
= NULL
;
6540 if (pwOrdinal
) *pwOrdinal
= 0;
6542 if (This
->TypeAttr
.typekind
!= TKIND_MODULE
)
6543 return TYPE_E_BADMODULEKIND
;
6545 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6546 if(pFDesc
->funcdesc
.memid
==memid
){
6547 dump_TypeInfo(This
);
6549 dump_TLBFuncDescOne(pFDesc
);
6552 *pBstrDllName
= SysAllocString(This
->DllName
);
6554 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
6556 *pBstrName
= SysAllocString(pFDesc
->Entry
);
6564 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
6567 return TYPE_E_ELEMENTNOTFOUND
;
6570 /* internal function to make the inherited interfaces' methods appear
6571 * part of the interface */
6572 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
6573 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
6575 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6578 TRACE("%p, 0x%x\n", iface
, *hRefType
);
6580 if (This
->impltypelist
&& (*hRefType
& DISPATCH_HREF_MASK
))
6582 ITypeInfo
*pSubTypeInfo
;
6584 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pSubTypeInfo
);
6588 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
6590 ITypeInfo_Release(pSubTypeInfo
);
6594 *hRefType
-= DISPATCH_HREF_OFFSET
;
6596 if (!(*hRefType
& DISPATCH_HREF_MASK
))
6597 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
6602 /* ITypeInfo::GetRefTypeInfo
6604 * If a type description references other type descriptions, it retrieves
6605 * the referenced type descriptions.
6607 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
6610 ITypeInfo
**ppTInfo
)
6612 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6613 HRESULT result
= E_FAIL
;
6615 if ((This
->hreftype
!= -1) && (This
->hreftype
== hRefType
))
6617 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6618 ITypeInfo_AddRef(*ppTInfo
);
6621 else if (hRefType
== -1 &&
6622 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
6623 (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
6625 /* when we meet a DUAL dispinterface, we must create the interface
6628 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
6631 /* the interface version contains the same information as the dispinterface
6632 * copy the contents of the structs.
6634 *pTypeInfoImpl
= *This
;
6635 pTypeInfoImpl
->ref
= 0;
6637 /* change the type to interface */
6638 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
6640 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
6642 /* we use data structures from This, so we need to keep a reference
6643 * to it to stop it being destroyed and signal to the new instance to
6644 * not free its data structures when it is destroyed */
6645 pTypeInfoImpl
->no_free_data
= TRUE
;
6646 pTypeInfoImpl
->next
= This
;
6647 ITypeInfo_AddRef((ITypeInfo
*) This
);
6649 ITypeInfo_AddRef(*ppTInfo
);
6653 } else if ((hRefType
!= -1) && (hRefType
& DISPATCH_HREF_MASK
) &&
6654 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
6655 (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
6657 HREFTYPE href_dispatch
= hRefType
;
6658 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
6660 TLBRefType
*ref_type
;
6661 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
6663 if(ref_type
->reference
== hRefType
)
6666 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
6668 FIXME("Can't find pRefType for ref %x\n", hRefType
);
6671 if(hRefType
!= -1) {
6672 ITypeLib
*pTLib
= NULL
;
6674 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
6676 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
6678 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
6679 TRACE("typeinfo in imported typelib that is already loaded\n");
6680 pTLib
= (ITypeLib
*)ref_type
->pImpTLInfo
->pImpTypeLib
;
6681 ITypeLib2_AddRef(pTLib
);
6684 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6685 result
= LoadRegTypeLib( &ref_type
->pImpTLInfo
->guid
,
6686 ref_type
->pImpTLInfo
->wVersionMajor
,
6687 ref_type
->pImpTLInfo
->wVersionMinor
,
6688 ref_type
->pImpTLInfo
->lcid
,
6691 if(FAILED(result
)) {
6692 BSTR libnam
=SysAllocString(ref_type
->pImpTLInfo
->name
);
6693 result
=LoadTypeLib(libnam
, &pTLib
);
6694 SysFreeString(libnam
);
6696 if(SUCCEEDED(result
)) {
6697 ref_type
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
6698 ITypeLib2_AddRef(pTLib
);
6702 if(SUCCEEDED(result
)) {
6703 if(ref_type
->index
== TLB_REF_USE_GUID
)
6704 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
6708 result
= ITypeLib2_GetTypeInfo(pTLib
, ref_type
->index
,
6712 ITypeLib2_Release(pTLib
);
6717 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
6718 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
6722 /* ITypeInfo::AddressOfMember
6724 * Retrieves the addresses of static functions or variables, such as those
6727 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
6728 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
6730 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6736 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
6738 hr
= ITypeInfo_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
6742 module
= LoadLibraryW(dll
);
6745 ERR("couldn't load %s\n", debugstr_w(dll
));
6747 SysFreeString(entry
);
6748 return STG_E_FILENOTFOUND
;
6750 /* FIXME: store library somewhere where we can free it */
6755 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
6756 entryA
= HeapAlloc(GetProcessHeap(), 0, len
);
6757 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
6759 *ppv
= GetProcAddress(module
, entryA
);
6761 ERR("function not found %s\n", debugstr_a(entryA
));
6763 HeapFree(GetProcessHeap(), 0, entryA
);
6767 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
6769 ERR("function not found %d\n", ordinal
);
6773 SysFreeString(entry
);
6776 return TYPE_E_DLLFUNCTIONNOTFOUND
;
6781 /* ITypeInfo::CreateInstance
6783 * Creates a new instance of a type that describes a component object class
6786 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
6787 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
6789 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6793 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
6799 WARN("Not able to aggregate\n");
6800 return CLASS_E_NOAGGREGATION
;
6803 hr
= ITypeInfo_GetTypeAttr(iface
, &pTA
);
6804 if(FAILED(hr
)) return hr
;
6806 if(pTA
->typekind
!= TKIND_COCLASS
)
6808 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
6814 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
6817 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
6818 TRACE("GetActiveObject rets %08x\n", hr
);
6821 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
6822 IUnknown_Release(pUnk
);
6827 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
6828 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
6832 ITypeInfo_ReleaseTypeAttr(iface
, pTA
);
6836 /* ITypeInfo::GetMops
6838 * Retrieves marshalling information.
6840 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
6843 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6844 FIXME("(%p) stub!\n", This
);
6848 /* ITypeInfo::GetContainingTypeLib
6850 * Retrieves the containing type library and the index of the type description
6851 * within that type library.
6853 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
6854 ITypeLib
* *ppTLib
, UINT
*pIndex
)
6856 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6858 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6860 *pIndex
=This
->index
;
6861 TRACE("returning pIndex=%d\n", *pIndex
);
6865 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
6866 ITypeLib2_AddRef(*ppTLib
);
6867 TRACE("returning ppTLib=%p\n", *ppTLib
);
6873 /* ITypeInfo::ReleaseTypeAttr
6875 * Releases a TYPEATTR previously returned by GetTypeAttr.
6878 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
6879 TYPEATTR
* pTypeAttr
)
6881 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6882 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
6883 HeapFree(GetProcessHeap(), 0, pTypeAttr
);
6886 /* ITypeInfo::ReleaseFuncDesc
6888 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6890 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
6892 FUNCDESC
*pFuncDesc
)
6894 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6897 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
6899 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6900 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
6901 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
6903 SysFreeString((BSTR
)pFuncDesc
);
6906 /* ITypeInfo::ReleaseVarDesc
6908 * Releases a VARDESC previously returned by GetVarDesc.
6910 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
6913 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6914 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
6916 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
6917 if (pVarDesc
->varkind
== VAR_CONST
)
6918 VariantClear(pVarDesc
->u
.lpvarValue
);
6919 SysFreeString((BSTR
)pVarDesc
);
6922 /* ITypeInfo2::GetTypeKind
6924 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6927 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
6928 TYPEKIND
*pTypeKind
)
6930 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6931 *pTypeKind
=This
->TypeAttr
.typekind
;
6932 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
6936 /* ITypeInfo2::GetTypeFlags
6938 * Returns the type flags without any allocations. This returns a DWORD type
6939 * flag, which expands the type flags without growing the TYPEATTR (type
6943 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
6945 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6946 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
6947 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
6951 /* ITypeInfo2::GetFuncIndexOfMemId
6952 * Binds to a specific member based on a known DISPID, where the member name
6953 * is not known (for example, when binding to a default member).
6956 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
6957 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
6959 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6960 const TLBFuncDesc
*pFuncInfo
;
6964 for(i
= 0, pFuncInfo
= This
->funclist
; pFuncInfo
; i
++, pFuncInfo
=pFuncInfo
->next
)
6965 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
6971 result
= TYPE_E_ELEMENTNOTFOUND
;
6973 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
6974 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
6978 /* TypeInfo2::GetVarIndexOfMemId
6980 * Binds to a specific member based on a known DISPID, where the member name
6981 * is not known (for example, when binding to a default member).
6984 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
6985 MEMBERID memid
, UINT
*pVarIndex
)
6987 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6988 TLBVarDesc
*pVarInfo
;
6991 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
6992 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
6998 result
= TYPE_E_ELEMENTNOTFOUND
;
7000 TRACE("(%p) memid 0x%08x -> %s\n", This
,
7001 memid
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7005 /* ITypeInfo2::GetCustData
7007 * Gets the custom data
7009 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7014 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7015 TLBCustData
*pCData
;
7017 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
7018 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7020 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7024 VariantInit( pVarVal
);
7025 VariantCopy( pVarVal
, &pCData
->data
);
7028 return E_INVALIDARG
; /* FIXME: correct? */
7031 /* ITypeInfo2::GetFuncCustData
7033 * Gets the custom data
7035 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
7041 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7042 TLBCustData
*pCData
=NULL
;
7043 TLBFuncDesc
* pFDesc
;
7045 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
7046 pFDesc
=pFDesc
->next
);
7049 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
7050 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7052 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7055 VariantInit( pVarVal
);
7056 VariantCopy( pVarVal
, &pCData
->data
);
7059 return E_INVALIDARG
; /* FIXME: correct? */
7062 /* ITypeInfo2::GetParamCustData
7064 * Gets the custom data
7066 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
7073 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7074 TLBCustData
*pCData
=NULL
;
7075 TLBFuncDesc
* pFDesc
;
7078 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
7080 if(pFDesc
&& indexParam
<pFDesc
->funcdesc
.cParams
)
7081 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
7082 pCData
= pCData
->next
)
7083 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7085 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7089 VariantInit( pVarVal
);
7090 VariantCopy( pVarVal
, &pCData
->data
);
7093 return E_INVALIDARG
; /* FIXME: correct? */
7096 /* ITypeInfo2::GetVarCustData
7098 * Gets the custom data
7100 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
7106 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7107 TLBCustData
*pCData
=NULL
;
7108 TLBVarDesc
* pVDesc
;
7111 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
7115 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
7117 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7121 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7125 VariantInit( pVarVal
);
7126 VariantCopy( pVarVal
, &pCData
->data
);
7129 return E_INVALIDARG
; /* FIXME: correct? */
7132 /* ITypeInfo2::GetImplCustData
7134 * Gets the custom data
7136 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
7142 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7143 TLBCustData
*pCData
=NULL
;
7144 TLBImplType
* pRDesc
;
7147 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
7151 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
7153 if( IsEqualIID(guid
, &pCData
->guid
)) break;
7157 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
7161 VariantInit( pVarVal
);
7162 VariantCopy( pVarVal
, &pCData
->data
);
7165 return E_INVALIDARG
; /* FIXME: correct? */
7168 /* ITypeInfo2::GetDocumentation2
7170 * Retrieves the documentation string, the complete Help file name and path,
7171 * the localization context to use, and the context ID for the library Help
7172 * topic in the Help file.
7175 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
7179 BSTR
*pbstrHelpString
,
7180 DWORD
*pdwHelpStringContext
,
7181 BSTR
*pbstrHelpStringDll
)
7183 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7184 const TLBFuncDesc
*pFDesc
;
7185 const TLBVarDesc
*pVDesc
;
7186 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7187 "HelpStringContext(%p) HelpStringDll(%p)\n",
7188 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
7189 pbstrHelpStringDll
);
7190 /* the help string should be obtained from the helpstringdll,
7191 * using the _DLLGetDocumentation function, based on the supplied
7192 * lcid. Nice to do sometime...
7194 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7196 *pbstrHelpString
=SysAllocString(This
->Name
);
7197 if(pdwHelpStringContext
)
7198 *pdwHelpStringContext
=This
->dwHelpStringContext
;
7199 if(pbstrHelpStringDll
)
7200 *pbstrHelpStringDll
=
7201 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7203 }else {/* for a member */
7204 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
7205 if(pFDesc
->funcdesc
.memid
==memid
){
7207 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
7208 if(pdwHelpStringContext
)
7209 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
7210 if(pbstrHelpStringDll
)
7211 *pbstrHelpStringDll
=
7212 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7215 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
7216 if(pVDesc
->vardesc
.memid
==memid
){
7218 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
7219 if(pdwHelpStringContext
)
7220 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
7221 if(pbstrHelpStringDll
)
7222 *pbstrHelpStringDll
=
7223 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7227 return TYPE_E_ELEMENTNOTFOUND
;
7230 /* ITypeInfo2::GetAllCustData
7232 * Gets all custom data items for the Type info.
7235 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
7237 CUSTDATA
*pCustData
)
7239 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7240 TLBCustData
*pCData
;
7243 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
7245 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
7246 if(pCustData
->prgCustData
){
7247 pCustData
->cCustData
=This
->ctCustData
;
7248 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
7249 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7250 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
7253 ERR(" OUT OF MEMORY!\n");
7254 return E_OUTOFMEMORY
;
7259 /* ITypeInfo2::GetAllFuncCustData
7261 * Gets all custom data items for the specified Function
7264 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
7267 CUSTDATA
*pCustData
)
7269 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7270 TLBCustData
*pCData
;
7271 TLBFuncDesc
* pFDesc
;
7273 TRACE("(%p) index %d\n", This
, index
);
7274 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
7275 pFDesc
=pFDesc
->next
)
7278 pCustData
->prgCustData
=
7279 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
7280 if(pCustData
->prgCustData
){
7281 pCustData
->cCustData
=pFDesc
->ctCustData
;
7282 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
7283 pCData
= pCData
->next
){
7284 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7285 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7289 ERR(" OUT OF MEMORY!\n");
7290 return E_OUTOFMEMORY
;
7294 return TYPE_E_ELEMENTNOTFOUND
;
7297 /* ITypeInfo2::GetAllParamCustData
7299 * Gets all custom data items for the Functions
7302 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
7303 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
7305 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7306 TLBCustData
*pCData
=NULL
;
7307 TLBFuncDesc
* pFDesc
;
7309 TRACE("(%p) index %d\n", This
, indexFunc
);
7310 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
7311 pFDesc
=pFDesc
->next
)
7313 if(pFDesc
&& indexParam
<pFDesc
->funcdesc
.cParams
){
7314 pCustData
->prgCustData
=
7315 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
7316 sizeof(CUSTDATAITEM
));
7317 if(pCustData
->prgCustData
){
7318 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
7319 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
7320 pCData
; i
++, pCData
= pCData
->next
){
7321 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7322 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7326 ERR(" OUT OF MEMORY!\n");
7327 return E_OUTOFMEMORY
;
7331 return TYPE_E_ELEMENTNOTFOUND
;
7334 /* ITypeInfo2::GetAllVarCustData
7336 * Gets all custom data items for the specified Variable
7339 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
7340 UINT index
, CUSTDATA
*pCustData
)
7342 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7343 TLBCustData
*pCData
;
7344 TLBVarDesc
* pVDesc
;
7346 TRACE("(%p) index %d\n", This
, index
);
7347 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
7348 pVDesc
=pVDesc
->next
)
7351 pCustData
->prgCustData
=
7352 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
7353 if(pCustData
->prgCustData
){
7354 pCustData
->cCustData
=pVDesc
->ctCustData
;
7355 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
7356 pCData
= pCData
->next
){
7357 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7358 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7362 ERR(" OUT OF MEMORY!\n");
7363 return E_OUTOFMEMORY
;
7367 return TYPE_E_ELEMENTNOTFOUND
;
7370 /* ITypeInfo2::GetAllImplCustData
7372 * Gets all custom data items for the specified implementation type
7375 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
7378 CUSTDATA
*pCustData
)
7380 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7381 TLBCustData
*pCData
;
7382 TLBImplType
* pRDesc
;
7384 TRACE("(%p) index %d\n", This
, index
);
7385 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
7386 pRDesc
=pRDesc
->next
)
7389 pCustData
->prgCustData
=
7390 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
7391 if(pCustData
->prgCustData
){
7392 pCustData
->cCustData
=pRDesc
->ctCustData
;
7393 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
7394 pCData
= pCData
->next
){
7395 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
7396 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
7400 ERR(" OUT OF MEMORY!\n");
7401 return E_OUTOFMEMORY
;
7405 return TYPE_E_ELEMENTNOTFOUND
;
7408 static const ITypeInfo2Vtbl tinfvt
=
7411 ITypeInfo_fnQueryInterface
,
7413 ITypeInfo_fnRelease
,
7415 ITypeInfo_fnGetTypeAttr
,
7416 ITypeInfo_fnGetTypeComp
,
7417 ITypeInfo_fnGetFuncDesc
,
7418 ITypeInfo_fnGetVarDesc
,
7419 ITypeInfo_fnGetNames
,
7420 ITypeInfo_fnGetRefTypeOfImplType
,
7421 ITypeInfo_fnGetImplTypeFlags
,
7422 ITypeInfo_fnGetIDsOfNames
,
7424 ITypeInfo_fnGetDocumentation
,
7425 ITypeInfo_fnGetDllEntry
,
7426 ITypeInfo_fnGetRefTypeInfo
,
7427 ITypeInfo_fnAddressOfMember
,
7428 ITypeInfo_fnCreateInstance
,
7429 ITypeInfo_fnGetMops
,
7430 ITypeInfo_fnGetContainingTypeLib
,
7431 ITypeInfo_fnReleaseTypeAttr
,
7432 ITypeInfo_fnReleaseFuncDesc
,
7433 ITypeInfo_fnReleaseVarDesc
,
7435 ITypeInfo2_fnGetTypeKind
,
7436 ITypeInfo2_fnGetTypeFlags
,
7437 ITypeInfo2_fnGetFuncIndexOfMemId
,
7438 ITypeInfo2_fnGetVarIndexOfMemId
,
7439 ITypeInfo2_fnGetCustData
,
7440 ITypeInfo2_fnGetFuncCustData
,
7441 ITypeInfo2_fnGetParamCustData
,
7442 ITypeInfo2_fnGetVarCustData
,
7443 ITypeInfo2_fnGetImplTypeCustData
,
7444 ITypeInfo2_fnGetDocumentation2
,
7445 ITypeInfo2_fnGetAllCustData
,
7446 ITypeInfo2_fnGetAllFuncCustData
,
7447 ITypeInfo2_fnGetAllParamCustData
,
7448 ITypeInfo2_fnGetAllVarCustData
,
7449 ITypeInfo2_fnGetAllImplTypeCustData
,
7452 /******************************************************************************
7453 * CreateDispTypeInfo [OLEAUT32.31]
7455 * Build type information for an object so it can be called through an
7456 * IDispatch interface.
7459 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7460 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7463 * This call allows an objects methods to be accessed through IDispatch, by
7464 * building an ITypeInfo object that IDispatch can use to call through.
7466 HRESULT WINAPI
CreateDispTypeInfo(
7467 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
7468 LCID lcid
, /* [I] Locale Id */
7469 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
7471 ITypeInfoImpl
*pTIClass
, *pTIIface
;
7472 ITypeLibImpl
*pTypeLibImpl
;
7473 unsigned int param
, func
;
7474 TLBFuncDesc
**ppFuncDesc
;
7478 pTypeLibImpl
= TypeLibImpl_Constructor();
7479 if (!pTypeLibImpl
) return E_FAIL
;
7481 pTIIface
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
7482 pTIIface
->pTypeLib
= pTypeLibImpl
;
7483 pTIIface
->index
= 0;
7484 pTIIface
->Name
= NULL
;
7485 pTIIface
->dwHelpContext
= -1;
7486 memset(&pTIIface
->TypeAttr
.guid
, 0, sizeof(GUID
));
7487 pTIIface
->TypeAttr
.lcid
= lcid
;
7488 pTIIface
->TypeAttr
.typekind
= TKIND_INTERFACE
;
7489 pTIIface
->TypeAttr
.wMajorVerNum
= 0;
7490 pTIIface
->TypeAttr
.wMinorVerNum
= 0;
7491 pTIIface
->TypeAttr
.cbAlignment
= 2;
7492 pTIIface
->TypeAttr
.cbSizeInstance
= -1;
7493 pTIIface
->TypeAttr
.cbSizeVft
= -1;
7494 pTIIface
->TypeAttr
.cFuncs
= 0;
7495 pTIIface
->TypeAttr
.cImplTypes
= 0;
7496 pTIIface
->TypeAttr
.cVars
= 0;
7497 pTIIface
->TypeAttr
.wTypeFlags
= 0;
7499 ppFuncDesc
= &pTIIface
->funclist
;
7500 for(func
= 0; func
< pidata
->cMembers
; func
++) {
7501 METHODDATA
*md
= pidata
->pmethdata
+ func
;
7502 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
7503 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
7504 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
7505 (*ppFuncDesc
)->funcdesc
.lprgscode
= NULL
;
7506 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_VIRTUAL
;
7507 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
7508 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
7509 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
7510 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
7511 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
<< 2;
7512 (*ppFuncDesc
)->funcdesc
.cScodes
= 0;
7513 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0;
7514 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
7515 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
7516 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
7517 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
7518 md
->cArgs
* sizeof(ELEMDESC
));
7519 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
7520 md
->cArgs
* sizeof(TLBParDesc
));
7521 for(param
= 0; param
< md
->cArgs
; param
++) {
7522 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
7523 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
7525 (*ppFuncDesc
)->helpcontext
= 0;
7526 (*ppFuncDesc
)->HelpStringContext
= 0;
7527 (*ppFuncDesc
)->HelpString
= NULL
;
7528 (*ppFuncDesc
)->Entry
= NULL
;
7529 (*ppFuncDesc
)->ctCustData
= 0;
7530 (*ppFuncDesc
)->pCustData
= NULL
;
7531 (*ppFuncDesc
)->next
= NULL
;
7532 pTIIface
->TypeAttr
.cFuncs
++;
7533 ppFuncDesc
= &(*ppFuncDesc
)->next
;
7536 dump_TypeInfo(pTIIface
);
7538 pTypeLibImpl
->pTypeInfo
= pTIIface
;
7539 pTypeLibImpl
->TypeInfoCount
++;
7541 pTIClass
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
7542 pTIClass
->pTypeLib
= pTypeLibImpl
;
7543 pTIClass
->index
= 1;
7544 pTIClass
->Name
= NULL
;
7545 pTIClass
->dwHelpContext
= -1;
7546 memset(&pTIClass
->TypeAttr
.guid
, 0, sizeof(GUID
));
7547 pTIClass
->TypeAttr
.lcid
= lcid
;
7548 pTIClass
->TypeAttr
.typekind
= TKIND_COCLASS
;
7549 pTIClass
->TypeAttr
.wMajorVerNum
= 0;
7550 pTIClass
->TypeAttr
.wMinorVerNum
= 0;
7551 pTIClass
->TypeAttr
.cbAlignment
= 2;
7552 pTIClass
->TypeAttr
.cbSizeInstance
= -1;
7553 pTIClass
->TypeAttr
.cbSizeVft
= -1;
7554 pTIClass
->TypeAttr
.cFuncs
= 0;
7555 pTIClass
->TypeAttr
.cImplTypes
= 1;
7556 pTIClass
->TypeAttr
.cVars
= 0;
7557 pTIClass
->TypeAttr
.wTypeFlags
= 0;
7559 pTIClass
->impltypelist
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pTIClass
->impltypelist
));
7560 pTIClass
->impltypelist
->hRef
= 0;
7562 ref
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref
));
7565 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
7566 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
7568 dump_TypeInfo(pTIClass
);
7570 pTIIface
->next
= pTIClass
;
7571 pTypeLibImpl
->TypeInfoCount
++;
7573 *pptinfo
= (ITypeInfo
*)pTIClass
;
7575 ITypeInfo_AddRef(*pptinfo
);
7576 ITypeLib_Release((ITypeLib
*)&pTypeLibImpl
->lpVtbl
);
7582 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
7584 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7586 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
7589 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
7591 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7593 return ITypeInfo_AddRef((ITypeInfo
*)This
);
7596 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
7598 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7600 return ITypeInfo_Release((ITypeInfo
*)This
);
7603 static HRESULT WINAPI
ITypeComp_fnBind(
7608 ITypeInfo
** ppTInfo
,
7609 DESCKIND
* pDescKind
,
7612 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7613 const TLBFuncDesc
*pFDesc
;
7614 const TLBVarDesc
*pVDesc
;
7615 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
7617 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7619 *pDescKind
= DESCKIND_NONE
;
7620 pBindPtr
->lpfuncdesc
= NULL
;
7623 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
7624 if (!strcmpiW(pFDesc
->Name
, szName
)) {
7625 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
7628 /* name found, but wrong flags */
7629 hr
= TYPE_E_TYPEMISMATCH
;
7634 HRESULT hr
= TLB_AllocAndInitFuncDesc(
7636 &pBindPtr
->lpfuncdesc
,
7637 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
7640 *pDescKind
= DESCKIND_FUNCDESC
;
7641 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7642 ITypeInfo_AddRef(*ppTInfo
);
7645 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
7646 if (!strcmpiW(pVDesc
->Name
, szName
)) {
7647 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
7650 *pDescKind
= DESCKIND_VARDESC
;
7651 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7652 ITypeInfo_AddRef(*ppTInfo
);
7657 /* FIXME: search each inherited interface, not just the first */
7658 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypelist
) {
7659 /* recursive search */
7663 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
7666 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
7667 ITypeInfo_Release(pTInfo
);
7671 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7672 ITypeComp_Release(pTComp
);
7675 WARN("Could not search inherited interface!\n");
7677 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
7681 static HRESULT WINAPI
ITypeComp_fnBindType(
7685 ITypeInfo
** ppTInfo
,
7686 ITypeComp
** ppTComp
)
7688 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
7690 /* strange behaviour (does nothing) but like the
7693 if (!ppTInfo
|| !ppTComp
)
7702 static const ITypeCompVtbl tcompvt
=
7705 ITypeComp_fnQueryInterface
,
7707 ITypeComp_fnRelease
,
7710 ITypeComp_fnBindType