4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
44 * -. lousy fatal error handling
49 #include "wine/port.h"
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
68 #include "wine/unicode.h"
71 #include "wine/debug.h"
73 #include "wine/list.h"
75 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
76 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
78 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
79 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
81 /****************************************************************************
84 * Takes p_iVal (which is in little endian) and returns it
85 * in the host machine's byte order.
87 #ifdef WORDS_BIGENDIAN
88 static WORD
FromLEWord(WORD p_iVal
)
90 return (((p_iVal
& 0x00FF) << 8) |
91 ((p_iVal
& 0xFF00) >> 8));
95 static DWORD
FromLEDWord(DWORD p_iVal
)
97 return (((p_iVal
& 0x000000FF) << 24) |
98 ((p_iVal
& 0x0000FF00) << 8) |
99 ((p_iVal
& 0x00FF0000) >> 8) |
100 ((p_iVal
& 0xFF000000) >> 24));
103 #define FromLEWord(X) (X)
104 #define FromLEDWord(X) (X)
108 /****************************************************************************
111 * Fix byte order in any structure if necessary
113 #ifdef WORDS_BIGENDIAN
114 static void FromLEWords(void *p_Val
, int p_iSize
)
118 p_iSize
/= sizeof(WORD
);
121 *Val
= FromLEWord(*Val
);
128 static void FromLEDWords(void *p_Val
, int p_iSize
)
132 p_iSize
/= sizeof(DWORD
);
135 *Val
= FromLEDWord(*Val
);
141 #define FromLEWords(X,Y) /*nothing*/
142 #define FromLEDWords(X,Y) /*nothing*/
146 * Find a typelib key which matches a requested maj.min version.
148 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
150 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
157 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
158 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
160 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
163 len
= sizeof(key_name
);
165 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
169 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
171 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
178 break; /* exact match */
180 if (v_min
> best_min
) best_min
= v_min
;
183 len
= sizeof(key_name
);
194 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
195 /* buffer must be at least 60 characters long */
196 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
198 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
199 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
201 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
202 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
203 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
207 /* get the path of an interface key, in the form "Interface\\<guid>" */
208 /* buffer must be at least 50 characters long */
209 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
211 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
213 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
214 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
218 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
219 /* buffer must be at least 16 characters long */
220 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
222 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
223 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
224 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
226 sprintfW( buffer
, LcidFormatW
, lcid
);
229 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
230 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
232 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
238 static int TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
241 /****************************************************************************
242 * QueryPathOfRegTypeLib [OLEAUT32.164]
244 * Gets the path to a registered type library.
247 * guid [I] referenced guid
248 * wMaj [I] major version
249 * wMin [I] minor version
251 * path [O] path of typelib
255 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
256 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
259 HRESULT WINAPI
QueryPathOfRegTypeLib(
266 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
270 WCHAR Path
[MAX_PATH
];
273 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
275 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
276 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
278 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
279 if (res
== ERROR_FILE_NOT_FOUND
)
281 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
282 return TYPE_E_LIBNOTREGISTERED
;
284 else if (res
!= ERROR_SUCCESS
)
286 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
287 return TYPE_E_REGISTRYACCESS
;
292 LONG dwPathLen
= sizeof(Path
);
294 get_lcid_subkey( myLCID
, SYS_WIN32
, buffer
);
296 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
300 else if (myLCID
== lcid
)
302 /* try with sub-langid */
303 myLCID
= SUBLANGID(lcid
);
305 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
307 /* try with system langid */
317 *path
= SysAllocString( Path
);
322 TRACE_(typelib
)("-- 0x%08x\n", hr
);
326 /******************************************************************************
327 * CreateTypeLib [OLEAUT32.160] creates a typelib
333 HRESULT WINAPI
CreateTypeLib(
334 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
336 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
340 /******************************************************************************
341 * LoadTypeLib [OLEAUT32.161]
343 * Loads a type library
346 * szFile [I] Name of file to load from.
347 * pptLib [O] Pointer that receives ITypeLib object on success.
354 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
356 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
358 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
359 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
362 /******************************************************************************
363 * LoadTypeLibEx [OLEAUT32.183]
365 * Loads and optionally registers a type library
371 HRESULT WINAPI
LoadTypeLibEx(
372 LPCOLESTR szFile
, /* [in] Name of file to load from */
373 REGKIND regkind
, /* [in] Specify kind of registration */
374 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
376 WCHAR szPath
[MAX_PATH
+1];
379 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
383 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
388 case REGKIND_DEFAULT
:
389 /* don't register typelibs supplied with full path. Experimentation confirms the following */
390 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
391 (szFile
[0] && (szFile
[1] == ':'))) break;
392 /* else fall-through */
394 case REGKIND_REGISTER
:
395 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szPath
, NULL
)))
397 IUnknown_Release(*pptLib
);
405 TRACE(" returns %08x\n",res
);
409 /******************************************************************************
410 * LoadRegTypeLib [OLEAUT32.162]
412 * Loads a registered type library.
415 * rguid [I] GUID of the registered type library.
416 * wVerMajor [I] major version.
417 * wVerMinor [I] minor version.
418 * lcid [I] locale ID.
419 * ppTLib [O] pointer that receives an ITypeLib object on success.
423 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
426 HRESULT WINAPI
LoadRegTypeLib(
438 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
442 res
= LoadTypeLib(bstr
, ppTLib
);
446 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
452 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
453 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
454 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
455 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
456 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
457 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
459 /******************************************************************************
460 * RegisterTypeLib [OLEAUT32.163]
461 * Adds information about a type library to the System Registry
463 * Docs: ITypeLib FAR * ptlib
464 * Docs: OLECHAR FAR* szFullPath
465 * Docs: OLECHAR FAR* szHelpDir
471 HRESULT WINAPI
RegisterTypeLib(
472 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
473 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
474 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
477 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
478 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
479 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
489 if (ptlib
== NULL
|| szFullPath
== NULL
)
492 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
495 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
498 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
499 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
503 /* Set the human-readable name of the typelib */
504 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
506 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
507 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
515 /* Make up the name of the typelib path subkey */
516 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
518 /* Create the typelib path subkey */
519 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
520 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
522 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
523 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
531 /* Create the flags subkey */
532 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
533 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
535 /* FIXME: is %u correct? */
536 static const WCHAR formatW
[] = {'%','u',0};
538 sprintfW(buf
, formatW
, attr
->wLibFlags
);
539 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
540 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
548 /* create the helpdir subkey */
549 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
550 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
552 BOOL freeHelpDir
= FALSE
;
555 /* if we created a new key, and helpDir was null, set the helpdir
556 to the directory which contains the typelib. However,
557 if we just opened an existing key, we leave the helpdir alone */
558 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
559 szHelpDir
= SysAllocString(szFullPath
);
560 pIndexStr
= strrchrW(szHelpDir
, '\\');
567 /* if we have an szHelpDir, set it! */
568 if (szHelpDir
!= NULL
) {
569 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
570 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
576 if (freeHelpDir
) SysFreeString(szHelpDir
);
588 /* register OLE Automation-compatible interfaces for this typelib */
589 types
= ITypeLib_GetTypeInfoCount(ptlib
);
590 for (tidx
=0; tidx
<types
; tidx
++) {
591 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
592 LPOLESTR name
= NULL
;
593 ITypeInfo
*tinfo
= NULL
;
595 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
598 case TKIND_INTERFACE
:
599 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
600 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
604 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
605 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
609 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
614 TYPEATTR
*tattr
= NULL
;
615 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
618 TRACE_(typelib
)("guid=%s, flags=%04x (",
619 debugstr_guid(&tattr
->guid
),
622 if (TRACE_ON(typelib
)) {
623 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
643 if (tattr
->wTypeFlags
& (TYPEFLAG_FOLEAUTOMATION
|TYPEFLAG_FDUAL
|TYPEFLAG_FDISPATCHABLE
))
645 /* register interface<->typelib coupling */
646 get_interface_key( &tattr
->guid
, keyName
);
647 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
648 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
651 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
652 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
654 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
655 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
656 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
657 (const BYTE
*)PSOA
, sizeof PSOA
);
661 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
662 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
663 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
664 (const BYTE
*)PSOA
, sizeof PSOA
);
668 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
669 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
672 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
673 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
675 StringFromGUID2(&attr
->guid
, buffer
, 40);
676 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
677 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
678 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
679 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
680 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
688 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
691 ITypeInfo_Release(tinfo
);
698 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
704 /******************************************************************************
705 * UnRegisterTypeLib [OLEAUT32.186]
706 * Removes information about a type library from the System Registry
713 HRESULT WINAPI
UnRegisterTypeLib(
714 REFGUID libid
, /* [in] Guid of the library */
715 WORD wVerMajor
, /* [in] major version */
716 WORD wVerMinor
, /* [in] minor version */
717 LCID lcid
, /* [in] locale id */
720 BSTR tlibPath
= NULL
;
723 WCHAR subKeyName
[50];
726 BOOL deleteOtherStuff
;
729 TYPEATTR
* typeAttr
= NULL
;
731 ITypeInfo
* typeInfo
= NULL
;
732 ITypeLib
* typeLib
= NULL
;
735 TRACE("(IID: %s)\n",debugstr_guid(libid
));
737 /* Create the path to the key */
738 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
740 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
)
742 TRACE("Unsupported syskind %i\n", syskind
);
743 result
= E_INVALIDARG
;
747 /* get the path to the typelib on disk */
748 if (QueryPathOfRegTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, &tlibPath
) != S_OK
) {
749 result
= E_INVALIDARG
;
753 /* Try and open the key to the type library. */
754 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
755 result
= E_INVALIDARG
;
759 /* Try and load the type library */
760 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
)) {
761 result
= TYPE_E_INVALIDSTATE
;
765 /* remove any types registered with this typelib */
766 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
767 for (i
=0; i
<numTypes
; i
++) {
768 /* get the kind of type */
769 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
773 /* skip non-interfaces, and get type info for the type */
774 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
777 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
780 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
784 /* the path to the type */
785 get_interface_key( &typeAttr
->guid
, subKeyName
);
787 /* Delete its bits */
788 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != ERROR_SUCCESS
) {
791 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
792 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
793 RegDeleteKeyW(subKey
, TypeLibW
);
796 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
799 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
801 if (typeInfo
) ITypeInfo_Release(typeInfo
);
805 /* Now, delete the type library path subkey */
806 get_lcid_subkey( lcid
, syskind
, subKeyName
);
807 RegDeleteKeyW(key
, subKeyName
);
808 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
809 RegDeleteKeyW(key
, subKeyName
);
811 /* check if there is anything besides the FLAGS/HELPDIR keys.
812 If there is, we don't delete them */
813 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
814 deleteOtherStuff
= TRUE
;
816 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
817 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
819 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
820 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
821 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
822 deleteOtherStuff
= FALSE
;
826 /* only delete the other parts of the key if we're absolutely sure */
827 if (deleteOtherStuff
) {
828 RegDeleteKeyW(key
, FLAGSW
);
829 RegDeleteKeyW(key
, HELPDIRW
);
833 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
834 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
835 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
839 if (tlibPath
) SysFreeString(tlibPath
);
840 if (typeLib
) ITypeLib_Release(typeLib
);
841 if (subKey
) RegCloseKey(subKey
);
842 if (key
) RegCloseKey(key
);
846 /*======================= ITypeLib implementation =======================*/
848 typedef struct tagTLBCustData
852 struct tagTLBCustData
* next
;
855 /* data structure for import typelibs */
856 typedef struct tagTLBImpLib
858 int offset
; /* offset in the file (MSFT)
859 offset in nametable (SLTG)
860 just used to identify library while reading
862 GUID guid
; /* libid */
863 BSTR name
; /* name */
865 LCID lcid
; /* lcid of imported typelib */
867 WORD wVersionMajor
; /* major version number */
868 WORD wVersionMinor
; /* minor version number */
870 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
871 NULL if not yet loaded */
872 struct tagTLBImpLib
* next
;
875 /* internal ITypeLib data */
876 typedef struct tagITypeLibImpl
878 const ITypeLib2Vtbl
*lpVtbl
;
879 const ITypeCompVtbl
*lpVtblTypeComp
;
881 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
883 /* strings can be stored in tlb as multibyte strings BUT they are *always*
884 * exported to the application as a UNICODE string.
890 unsigned long dwHelpContext
;
891 int TypeInfoCount
; /* nr of typeinfo's in librarry */
892 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
893 int ctCustData
; /* number of items in cust data list */
894 TLBCustData
* pCustData
; /* linked list to cust data */
895 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
896 int ctTypeDesc
; /* number of items in type desc array */
897 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
898 library. Only used while reading MSFT
900 struct list ref_list
; /* list of ref types in this typelib */
901 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
904 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
905 struct tagITypeLibImpl
*next
, *prev
;
910 static const ITypeLib2Vtbl tlbvt
;
911 static const ITypeCompVtbl tlbtcvt
;
913 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
915 return (ITypeLibImpl
*)((char*)iface
- FIELD_OFFSET(ITypeLibImpl
, lpVtblTypeComp
));
918 /* ITypeLib methods */
919 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
920 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
922 /*======================= ITypeInfo implementation =======================*/
924 /* data for referenced types */
925 typedef struct tagTLBRefType
927 INT index
; /* Type index for internal ref or for external ref
928 it the format is SLTG. -2 indicates to
931 GUID guid
; /* guid of the referenced type */
932 /* if index == TLB_REF_USE_GUID */
934 HREFTYPE reference
; /* The href of this ref */
935 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
936 TLB_REF_INTERNAL for internal refs
937 TLB_REF_NOT_FOUND for broken refs */
942 #define TLB_REF_USE_GUID -2
944 #define TLB_REF_INTERNAL (void*)-2
945 #define TLB_REF_NOT_FOUND (void*)-1
947 /* internal Parameter data */
948 typedef struct tagTLBParDesc
952 TLBCustData
* pCustData
; /* linked list to cust data */
955 /* internal Function data */
956 typedef struct tagTLBFuncDesc
958 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
959 BSTR Name
; /* the name of this function */
960 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
962 int HelpStringContext
;
964 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
966 TLBCustData
* pCustData
; /* linked list to cust data; */
967 struct tagTLBFuncDesc
* next
;
970 /* internal Variable data */
971 typedef struct tagTLBVarDesc
973 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
974 BSTR Name
; /* the name of this variable */
976 int HelpStringContext
; /* FIXME: where? */
979 TLBCustData
* pCustData
;/* linked list to cust data; */
980 struct tagTLBVarDesc
* next
;
983 /* internal implemented interface data */
984 typedef struct tagTLBImplType
986 HREFTYPE hRef
; /* hRef of interface */
987 int implflags
; /* IMPLFLAG_*s */
989 TLBCustData
* pCustData
;/* linked list to custom data; */
990 struct tagTLBImplType
*next
;
993 /* internal TypeInfo data */
994 typedef struct tagITypeInfoImpl
996 const ITypeInfo2Vtbl
*lpVtbl
;
997 const ITypeCompVtbl
*lpVtblTypeComp
;
999 BOOL no_free_data
; /* don't free data structurees */
1000 TYPEATTR TypeAttr
; /* _lots_ of type information. */
1001 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1002 int index
; /* index in this typelib; */
1003 HREFTYPE hreftype
; /* hreftype for app object binding */
1004 /* type libs seem to store the doc strings in ascii
1005 * so why should we do it in unicode?
1010 unsigned long dwHelpContext
;
1011 unsigned long dwHelpStringContext
;
1014 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
1017 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
1019 /* Implemented Interfaces */
1020 TLBImplType
* impltypelist
;
1023 TLBCustData
* pCustData
; /* linked list to cust data; */
1024 struct tagITypeInfoImpl
* next
;
1027 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1029 return (ITypeInfoImpl
*)((char*)iface
- FIELD_OFFSET(ITypeInfoImpl
, lpVtblTypeComp
));
1032 static const ITypeInfo2Vtbl tinfvt
;
1033 static const ITypeCompVtbl tcompvt
;
1035 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void);
1037 typedef struct tagTLBContext
1039 unsigned int oStart
; /* start of TLB in file */
1040 unsigned int pos
; /* current pos */
1041 unsigned int length
; /* total length */
1042 void *mapping
; /* memory mapping */
1043 MSFT_SegDir
* pTblDir
;
1044 ITypeLibImpl
* pLibInfo
;
1048 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
, int offset
);
1053 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1054 if (pTD
->vt
& VT_RESERVED
)
1055 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1056 if (pTD
->vt
& VT_BYREF
)
1057 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1058 if (pTD
->vt
& VT_ARRAY
)
1059 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1060 if (pTD
->vt
& VT_VECTOR
)
1061 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1062 switch(pTD
->vt
& VT_TYPEMASK
) {
1063 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1064 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1065 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1066 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1067 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1068 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1069 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1070 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1071 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1072 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1073 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1074 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1075 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1076 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1077 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1078 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1079 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1080 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1081 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1082 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1083 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1084 pTD
->u
.hreftype
); break;
1085 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1086 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1088 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1089 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1091 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1092 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1093 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1096 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1100 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1102 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1103 dump_TypeDesc(&edesc
->tdesc
,buf
);
1104 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1105 MESSAGE("\t\tu.paramdesc.wParamFlags");
1106 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1107 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1108 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1109 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1110 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1111 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1112 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1113 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1114 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1116 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1118 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1119 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1120 MESSAGE("Param %d:\n",i
);
1121 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1123 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1124 switch (funcdesc
->funckind
) {
1125 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1126 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1127 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1128 case FUNC_STATIC
: MESSAGE("static");break;
1129 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1130 default: MESSAGE("unknown");break;
1132 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1133 switch (funcdesc
->invkind
) {
1134 case INVOKE_FUNC
: MESSAGE("func");break;
1135 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1136 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1137 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1139 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1140 switch (funcdesc
->callconv
) {
1141 case CC_CDECL
: MESSAGE("cdecl");break;
1142 case CC_PASCAL
: MESSAGE("pascal");break;
1143 case CC_STDCALL
: MESSAGE("stdcall");break;
1144 case CC_SYSCALL
: MESSAGE("syscall");break;
1147 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1148 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1149 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1151 MESSAGE("\telemdescFunc (return value type):\n");
1152 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1155 static const char * const typekind_desc
[] =
1168 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1171 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1172 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1173 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1176 dump_FUNCDESC(&(pfd
->funcdesc
));
1178 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1179 MESSAGE("\tentry: %s\n", (pfd
->Entry
== (void *)-1) ? "invalid" : debugstr_w(pfd
->Entry
));
1181 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
)
1185 dump_TLBFuncDescOne(pfd
);
1189 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
)
1193 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1198 static void dump_TLBImpLib(const TLBImpLib
*import
)
1200 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1201 debugstr_w(import
->name
));
1202 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1203 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1206 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1210 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1212 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1213 if(ref
->index
== -1)
1214 TRACE_(typelib
)("%s\n", debugstr_guid(&(ref
->guid
)));
1216 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1218 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1220 TRACE_(typelib
)("in lib\n");
1221 dump_TLBImpLib(ref
->pImpTLInfo
);
1226 static void dump_TLBImplType(const TLBImplType
* impl
)
1230 "implementing/inheriting interface hRef = %x implflags %x\n",
1231 impl
->hRef
, impl
->implflags
);
1236 static void dump_Variant(const VARIANT
* pvar
)
1240 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1244 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1245 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1247 TRACE(",%p", V_BYREF(pvar
));
1249 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1251 TRACE(",%p", V_ARRAY(pvar
));
1253 else switch (V_TYPE(pvar
))
1255 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1256 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1257 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1258 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1260 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1262 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1263 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1264 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1265 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1266 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1267 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1268 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1269 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1270 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1271 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1272 V_CY(pvar
).s
.Lo
); break;
1274 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1275 TRACE(",<invalid>");
1277 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1278 st
.wHour
, st
.wMinute
, st
.wSecond
);
1282 case VT_USERDEFINED
:
1284 case VT_NULL
: break;
1285 default: TRACE(",?"); break;
1291 static void dump_DispParms(const DISPPARAMS
* pdp
)
1295 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1297 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1299 TRACE("named args:\n");
1300 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1301 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1304 if (pdp
->cArgs
&& pdp
->rgvarg
)
1307 for (index
= 0; index
< pdp
->cArgs
; index
++)
1308 dump_Variant( &pdp
->rgvarg
[index
] );
1312 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1314 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1315 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1316 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1317 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1318 TRACE("fct:%u var:%u impl:%u\n",
1319 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1320 TRACE("wTypeFlags: 0x%04x\n", pty
->TypeAttr
.wTypeFlags
);
1321 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1322 if (pty
->TypeAttr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(pty
->DllName
));
1324 dump_TLBFuncDesc(pty
->funclist
);
1325 dump_TLBVarDesc(pty
->varlist
);
1326 dump_TLBImplType(pty
->impltypelist
);
1329 static void dump_VARDESC(const VARDESC
*v
)
1331 MESSAGE("memid %d\n",v
->memid
);
1332 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1333 MESSAGE("oInst %d\n",v
->u
.oInst
);
1334 dump_ELEMDESC(&(v
->elemdescVar
));
1335 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1336 MESSAGE("varkind %d\n",v
->varkind
);
1339 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1341 /* VT_LPWSTR is largest type that */
1342 /* may appear in type description*/
1343 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1344 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1345 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1346 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1347 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1348 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1352 static void TLB_abort(void)
1356 static void * TLB_Alloc(unsigned size
)
1359 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1361 ERR("cannot allocate memory\n");
1366 static void TLB_Free(void * ptr
)
1368 HeapFree(GetProcessHeap(), 0, ptr
);
1371 /* returns the size required for a deep copy of a typedesc into a
1373 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1377 if (alloc_initial_space
)
1378 size
+= sizeof(TYPEDESC
);
1384 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1387 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1388 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1394 /* deep copy a typedesc into a flat buffer */
1395 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1400 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1409 dest
->u
.lptdesc
= buffer
;
1410 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1413 dest
->u
.lpadesc
= buffer
;
1414 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1415 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1416 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1422 /**********************************************************************
1424 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1426 static inline unsigned int MSFT_Tell(TLBContext
*pcx
)
1431 static inline void MSFT_Seek(TLBContext
*pcx
, long where
)
1433 if (where
!= DO_NOT_SEEK
)
1435 where
+= pcx
->oStart
;
1436 if (where
> pcx
->length
)
1439 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1447 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1449 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1450 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1452 MSFT_Seek(pcx
, where
);
1453 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1454 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1459 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1464 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1465 FromLEDWords(buffer
, ret
);
1470 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1475 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1476 FromLEWords(buffer
, ret
);
1481 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1483 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1484 memset(pGuid
,0, sizeof(GUID
));
1487 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1488 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1489 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1490 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1491 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1494 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
1496 MSFT_NameIntro niName
;
1500 ERR_(typelib
)("bad offset %d\n", offset
);
1504 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1505 pcx
->pTblDir
->pNametab
.offset
+offset
);
1507 return niName
.hreftype
;
1510 static BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1513 MSFT_NameIntro niName
;
1515 BSTR bstrName
= NULL
;
1519 ERR_(typelib
)("bad offset %d\n", offset
);
1522 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1523 pcx
->pTblDir
->pNametab
.offset
+offset
);
1524 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1525 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1526 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1527 name
[niName
.namelen
& 0xff]='\0';
1529 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1532 /* no invalid characters in string */
1535 bstrName
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1537 /* don't check for invalid character since this has been done previously */
1538 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, bstrName
, lengthInChars
);
1542 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1546 static BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1553 if(offset
<0) return NULL
;
1554 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1555 if(length
<= 0) return 0;
1556 string
=TLB_Alloc(length
+1);
1557 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1558 string
[length
]='\0';
1560 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1561 string
, -1, NULL
, 0);
1563 /* no invalid characters in string */
1566 bstr
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1568 /* don't check for invalid character since this has been done previously */
1569 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, bstr
, lengthInChars
);
1573 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1577 * read a value and fill a VARIANT structure
1579 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1583 TRACE_(typelib
)("\n");
1585 if(offset
<0) { /* data are packed in here */
1586 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1587 V_I4(pVar
) = offset
& 0x3ffffff;
1590 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1591 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1592 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1593 switch (V_VT(pVar
)){
1594 case VT_EMPTY
: /* FIXME: is this right? */
1595 case VT_NULL
: /* FIXME: is this right? */
1596 case VT_I2
: /* this should not happen */
1607 case VT_VOID
: /* FIXME: is this right? */
1615 case VT_DECIMAL
: /* FIXME: is this right? */
1618 /* pointer types with known behaviour */
1621 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1624 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
1627 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
1629 nullPos
= MSFT_Tell(pcx
);
1630 size
= nullPos
- origPos
;
1631 MSFT_Seek(pcx
, origPos
);
1633 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1634 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1635 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1636 /* FIXME: do we need a AtoW conversion here? */
1637 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1638 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1642 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1649 case VT_USERDEFINED
:
1655 case VT_STREAMED_OBJECT
:
1656 case VT_STORED_OBJECT
:
1657 case VT_BLOB_OBJECT
:
1662 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1666 if(size
>0) /* (big|small) endian correct? */
1667 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1671 * create a linked list with custom data
1673 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1679 TRACE_(typelib
)("\n");
1683 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1684 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1685 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1686 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1687 /* add new custom data at head of the list */
1688 pNew
->next
=*ppCustData
;
1690 offset
= entry
.next
;
1695 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1699 pTd
->vt
=type
& VT_TYPEMASK
;
1701 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1703 if(pTd
->vt
== VT_USERDEFINED
)
1704 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, pTd
->u
.hreftype
);
1706 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1709 static void MSFT_ResolveReferencedTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, TYPEDESC
*lpTypeDesc
)
1711 /* resolve referenced type if any */
1714 switch (lpTypeDesc
->vt
)
1717 lpTypeDesc
= lpTypeDesc
->u
.lptdesc
;
1721 lpTypeDesc
= & (lpTypeDesc
->u
.lpadesc
->tdescElem
);
1724 case VT_USERDEFINED
:
1725 MSFT_DoRefType(pcx
, pTI
->pTypeLib
,
1726 lpTypeDesc
->u
.hreftype
);
1738 MSFT_DoFuncs(TLBContext
* pcx
,
1743 TLBFuncDesc
** pptfd
)
1746 * member information is stored in a data structure at offset
1747 * indicated by the memoffset field of the typeinfo structure
1748 * There are several distinctive parts.
1749 * The first part starts with a field that holds the total length
1750 * of this (first) part excluding this field. Then follow the records,
1751 * for each member there is one record.
1753 * The first entry is always the length of the record (including this
1755 * The rest of the record depends on the type of the member. If there is
1756 * a field indicating the member type (function, variable, interface, etc)
1757 * I have not found it yet. At this time we depend on the information
1758 * in the type info and the usual order how things are stored.
1760 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1763 * Third is an equal sized array with file offsets to the name entry
1766 * The fourth and last (?) part is an array with offsets to the records
1767 * in the first part of this file segment.
1770 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1771 int recoffset
= offset
+ sizeof(INT
);
1773 char *recbuf
= HeapAlloc(GetProcessHeap(), 0, 0xffff);
1774 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1775 TLBFuncDesc
*ptfd_prev
= NULL
;
1777 TRACE_(typelib
)("\n");
1779 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1781 for ( i
= 0; i
< cFuncs
; i
++ )
1783 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1785 /* name, eventually add to a hash table */
1786 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1787 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1789 /* nameoffset is sometimes -1 on the second half of a propget/propput
1790 * pair of functions */
1791 if ((nameoffset
== -1) && (i
> 0))
1792 (*pptfd
)->Name
= SysAllocString(ptfd_prev
->Name
);
1794 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1796 /* read the function information record */
1797 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1799 reclength
&= 0xffff;
1801 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1803 /* do the attributes */
1804 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1807 if ( nrattributes
> 0 )
1809 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1811 if ( nrattributes
> 1 )
1813 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1814 pFuncRec
->OptAttr
[1]) ;
1816 if ( nrattributes
> 2 )
1818 if ( pFuncRec
->FKCCIC
& 0x2000 )
1820 if (HIWORD(pFuncRec
->OptAttr
[2]) != 0)
1821 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec
->OptAttr
[2]);
1822 (*pptfd
)->Entry
= (BSTR
)pFuncRec
->OptAttr
[2];
1826 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1827 pFuncRec
->OptAttr
[2]);
1829 if( nrattributes
> 5 )
1831 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1833 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1836 pFuncRec
->OptAttr
[6],
1837 &(*pptfd
)->pCustData
);
1843 (*pptfd
)->Entry
= (BSTR
)-1;
1848 /* fill the FuncDesc Structure */
1849 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1850 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1852 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1853 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1854 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1855 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1856 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1857 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1858 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1862 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1864 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
);
1866 /* do the parameters/arguments */
1867 if(pFuncRec
->nrargs
)
1870 MSFT_ParameterInfo paraminfo
;
1872 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1873 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1875 (*pptfd
)->pParamDesc
=
1876 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1878 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1879 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1881 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1883 ELEMDESC
*elemdesc
= &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1890 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1893 if (paraminfo
.oName
== -1)
1894 /* this occurs for [propput] or [propget] methods, so
1895 * we should just set the name of the parameter to the
1896 * name of the method. */
1897 (*pptfd
)->pParamDesc
[j
].Name
= SysAllocString((*pptfd
)->Name
);
1899 (*pptfd
)->pParamDesc
[j
].Name
=
1900 MSFT_ReadName( pcx
, paraminfo
.oName
);
1901 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w((*pptfd
)->pParamDesc
[j
].Name
));
1903 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
1906 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
1907 (pFuncRec
->FKCCIC
& 0x1000) )
1909 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1911 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1913 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
1915 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1916 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1918 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1922 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
1924 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1927 pFuncRec
->OptAttr
[7+j
],
1928 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1931 /* SEEK value = jump to offset,
1932 * from there jump to the end of record,
1933 * go back by (j-1) arguments
1935 MSFT_ReadLEDWords( ¶minfo
,
1936 sizeof(MSFT_ParameterInfo
), pcx
,
1937 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1938 * sizeof(MSFT_ParameterInfo
)));
1942 /* scode is not used: archaic win16 stuff FIXME: right? */
1943 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1944 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1947 pptfd
= & ((*pptfd
)->next
);
1948 recoffset
+= reclength
;
1950 HeapFree(GetProcessHeap(), 0, recbuf
);
1953 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1954 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1956 int infolen
, nameoffset
, reclength
;
1958 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1962 TRACE_(typelib
)("\n");
1964 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1965 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1966 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1967 recoffset
+= offset
+sizeof(INT
);
1968 for(i
=0;i
<cVars
;i
++){
1969 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1970 /* name, eventually add to a hash table */
1971 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1972 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1973 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1974 /* read the variable information record */
1975 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1977 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1979 if(reclength
>(6*sizeof(INT
)) )
1980 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1981 if(reclength
>(7*sizeof(INT
)) )
1982 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1983 if(reclength
>(8*sizeof(INT
)) )
1984 if(reclength
>(9*sizeof(INT
)) )
1985 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1986 /* fill the VarDesc Structure */
1987 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1988 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
1989 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1990 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1991 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1992 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1993 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1994 if(pVarRec
->VarKind
== VAR_CONST
){
1995 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1996 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1997 pVarRec
->OffsValue
, pcx
);
1999 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2000 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptvd
)->vardesc
.elemdescVar
.tdesc
);
2001 pptvd
=&((*pptvd
)->next
);
2002 recoffset
+= reclength
;
2005 /* fill in data for a hreftype (offset). When the referenced type is contained
2006 * in the typelib, it's just an (file) offset in the type info base dir.
2007 * If comes from import, it's an offset+1 in the ImpInfo table
2009 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
,
2015 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2017 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
2019 if(ref
->reference
== offset
) return;
2022 ref
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref
));
2023 list_add_tail(&pTL
->ref_list
, &ref
->entry
);
2025 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2026 /* external typelib */
2027 MSFT_ImpInfo impinfo
;
2028 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
2030 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2032 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2033 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2034 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
2035 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
2036 pImpLib
=pImpLib
->next
;
2039 ref
->reference
= offset
;
2040 ref
->pImpTLInfo
= pImpLib
;
2041 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2042 MSFT_ReadGuid(&ref
->guid
, impinfo
.oGuid
, pcx
);
2043 TRACE("importing by guid %s\n", debugstr_guid(&ref
->guid
));
2044 ref
->index
= TLB_REF_USE_GUID
;
2046 ref
->index
= impinfo
.oGuid
;
2048 ERR("Cannot find a reference\n");
2049 ref
->reference
= -1;
2050 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2053 /* in this typelib */
2054 ref
->index
= MSFT_HREFTYPE_INDEX(offset
);
2055 ref
->reference
= offset
;
2056 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
2060 /* process Implemented Interfaces of a com class */
2061 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2065 MSFT_RefRecord refrec
;
2066 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
2068 TRACE_(typelib
)("\n");
2070 for(i
=0;i
<count
;i
++){
2071 if(offset
<0) break; /* paranoia */
2072 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
2073 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2074 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, refrec
.reftype
);
2075 (*ppImpl
)->hRef
= refrec
.reftype
;
2076 (*ppImpl
)->implflags
=refrec
.flags
;
2077 (*ppImpl
)->ctCustData
=
2078 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
2079 offset
=refrec
.onext
;
2080 ppImpl
=&((*ppImpl
)->next
);
2084 * process a typeinfo record
2086 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2089 ITypeLibImpl
* pLibInfo
)
2091 MSFT_TypeInfoBase tiBase
;
2092 ITypeInfoImpl
*ptiRet
;
2094 TRACE_(typelib
)("count=%u\n", count
);
2096 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
2097 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2098 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2100 /* this is where we are coming from */
2101 ptiRet
->pTypeLib
= pLibInfo
;
2102 ptiRet
->index
=count
;
2103 /* fill in the typeattr fields */
2105 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2106 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2107 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2108 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2109 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2110 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2111 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2112 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2113 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2114 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2115 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2116 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2117 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2118 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2119 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2120 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2123 /* IDLDESC idldescType; *//* never saw this one != zero */
2125 /* name, eventually add to a hash table */
2126 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2127 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2128 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2130 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2131 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2132 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2134 if (ptiRet
->TypeAttr
.typekind
== TKIND_MODULE
)
2135 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2137 /* note: InfoType's Help file and HelpStringDll come from the containing
2138 * library. Further HelpString and Docstring appear to be the same thing :(
2141 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2142 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2143 ptiRet
->TypeAttr
.cVars
,
2144 tiBase
.memoffset
, & ptiRet
->funclist
);
2146 if(ptiRet
->TypeAttr
.cVars
>0 )
2147 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2148 ptiRet
->TypeAttr
.cVars
,
2149 tiBase
.memoffset
, & ptiRet
->varlist
);
2150 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2151 switch(ptiRet
->TypeAttr
.typekind
)
2154 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2157 case TKIND_DISPATCH
:
2158 /* This is not -1 when the interface is a non-base dual interface or
2159 when a dispinterface wraps an interface ie the idl 'dispinterface x {interface y;};'.
2160 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2164 if (tiBase
.datatype1
!= -1)
2166 ptiRet
->impltypelist
= TLB_Alloc(sizeof(TLBImplType
));
2167 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2168 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2172 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2173 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2174 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2179 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2181 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2182 debugstr_w(ptiRet
->Name
),
2183 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2184 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2189 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2190 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2191 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2194 static ITypeLibImpl
*tlb_cache_first
;
2195 static CRITICAL_SECTION cache_section
;
2196 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2198 0, 0, &cache_section
,
2199 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2200 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2202 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2205 /****************************************************************************
2208 * find the type of the typelib file and map the typelib resource into
2211 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2212 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2213 static int TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
2215 ITypeLibImpl
*entry
;
2216 int ret
= TYPE_E_CANTLOADLIBRARY
;
2219 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
2223 index_str
= strrchrW(pszFileName
, '\\');
2224 if(index_str
&& *++index_str
!= '\0')
2227 long idx
= strtolW(index_str
, &end_ptr
, 10);
2228 if(*end_ptr
== '\0')
2230 int str_len
= index_str
- pszFileName
- 1;
2232 file
= HeapAlloc(GetProcessHeap(), 0, (str_len
+ 1) * sizeof(WCHAR
));
2233 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
2238 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
2240 if(strchrW(file
, '\\'))
2242 lstrcpyW(pszPath
, file
);
2246 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
2247 pszPath
[len
] = '\\';
2248 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
2252 if(file
!= pszFileName
) HeapFree(GetProcessHeap(), 0, file
);
2254 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
2256 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2257 EnterCriticalSection(&cache_section
);
2258 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2260 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
2262 TRACE("cache hit\n");
2263 *ppTypeLib
= (ITypeLib2
*)entry
;
2264 ITypeLib_AddRef(*ppTypeLib
);
2265 LeaveCriticalSection(&cache_section
);
2269 LeaveCriticalSection(&cache_section
);
2271 /* now actually load and parse the typelib */
2273 hinstDLL
= LoadLibraryExW(pszPath
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2274 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2278 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2279 HRSRC hrsrc
= FindResourceW(hinstDLL
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2282 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2285 LPVOID pBase
= LockResource(hGlobal
);
2286 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2290 /* try to load as incore resource */
2291 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2292 if (dwSignature
== MSFT_SIGNATURE
)
2293 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2294 else if (dwSignature
== SLTG_SIGNATURE
)
2295 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2297 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
2299 FreeResource( hGlobal
);
2302 FreeLibrary(hinstDLL
);
2306 HANDLE hFile
= CreateFileW(pszPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
2307 if (INVALID_HANDLE_VALUE
!= hFile
)
2309 HANDLE hMapping
= CreateFileMappingW( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2312 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
2315 /* retrieve file size */
2316 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
2317 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2319 if (dwSignature
== MSFT_SIGNATURE
)
2320 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2321 else if (dwSignature
== SLTG_SIGNATURE
)
2322 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2324 UnmapViewOfFile(pBase
);
2326 CloseHandle(hMapping
);
2333 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2335 TRACE("adding to cache\n");
2336 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath
)+1) * sizeof(WCHAR
));
2337 lstrcpyW(impl
->path
, pszPath
);
2338 /* We should really canonicalise the path here. */
2339 impl
->index
= index
;
2341 /* FIXME: check if it has added already in the meantime */
2342 EnterCriticalSection(&cache_section
);
2343 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2345 tlb_cache_first
= impl
;
2346 LeaveCriticalSection(&cache_section
);
2349 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
2354 /*================== ITypeLib(2) Methods ===================================*/
2356 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
2358 ITypeLibImpl
* pTypeLibImpl
;
2360 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2361 if (!pTypeLibImpl
) return NULL
;
2363 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2364 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2365 pTypeLibImpl
->ref
= 1;
2367 list_init(&pTypeLibImpl
->ref_list
);
2368 pTypeLibImpl
->dispatch_href
= -1;
2370 return pTypeLibImpl
;
2373 /****************************************************************************
2374 * ITypeLib2_Constructor_MSFT
2376 * loading an MSFT typelib from an in-memory image
2378 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2382 MSFT_Header tlbHeader
;
2383 MSFT_SegDir tlbSegDir
;
2384 ITypeLibImpl
* pTypeLibImpl
;
2386 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
2388 pTypeLibImpl
= TypeLibImpl_Constructor();
2389 if (!pTypeLibImpl
) return NULL
;
2391 /* get pointer to beginning of typelib data */
2395 cx
.pLibInfo
= pTypeLibImpl
;
2396 cx
.length
= dwTLBLength
;
2399 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2400 TRACE_(typelib
)("header:\n");
2401 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2402 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2403 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2406 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
2408 /* there is a small amount of information here until the next important
2410 * the segment directory . Try to calculate the amount of data */
2411 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2413 /* now read the segment directory */
2414 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2415 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2416 cx
.pTblDir
= &tlbSegDir
;
2418 /* just check two entries */
2419 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2421 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2422 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2426 /* now fill our internal data */
2427 /* TLIBATTR fields */
2428 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2430 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2431 /* Windows seems to have zero here, is this correct? */
2432 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2433 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader
.lcid
),0),0);
2435 pTypeLibImpl
->LibAttr
.lcid
= 0;
2437 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2438 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2439 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2440 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2442 /* name, eventually add to a hash table */
2443 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2446 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2447 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2449 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2452 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2453 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2456 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2459 if(tlbHeader
.CustomDataOffset
>= 0)
2461 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2464 /* fill in typedescriptions */
2465 if(tlbSegDir
.pTypdescTab
.length
> 0)
2467 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2469 pTypeLibImpl
->ctTypeDesc
= cTD
;
2470 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2471 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2474 /* FIXME: add several sanity checks here */
2475 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2476 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2478 /* FIXME: check safearray */
2480 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2482 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2484 else if(td
[0] == VT_CARRAY
)
2486 /* array descr table here */
2487 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2489 else if(td
[0] == VT_USERDEFINED
)
2491 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2493 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2496 /* second time around to fill the array subscript info */
2499 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2500 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2502 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2503 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2506 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2508 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2510 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2512 for(j
= 0; j
<td
[2]; j
++)
2514 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2515 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2516 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2517 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2522 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2523 ERR("didn't find array description data\n");
2528 /* imported type libs */
2529 if(tlbSegDir
.pImpFiles
.offset
>0)
2531 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2532 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2535 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2540 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2541 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2542 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2544 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2545 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2546 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2547 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2550 name
= TLB_Alloc(size
+1);
2551 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2552 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
2553 (*ppImpLib
)->name
= TLB_Alloc(len
* sizeof(WCHAR
));
2554 MultiByteToWideChar(CP_ACP
, 0, name
, -1, (*ppImpLib
)->name
, len
);
2557 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2558 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2560 ppImpLib
= &(*ppImpLib
)->next
;
2564 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
2565 if(pTypeLibImpl
->dispatch_href
!= -1)
2566 MSFT_DoRefType(&cx
, pTypeLibImpl
, pTypeLibImpl
->dispatch_href
);
2569 if(tlbHeader
.nrtypeinfos
>= 0 )
2571 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2572 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2575 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2577 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2579 ppTI
= &((*ppTI
)->next
);
2580 (pTypeLibImpl
->TypeInfoCount
)++;
2584 TRACE("(%p)\n", pTypeLibImpl
);
2585 return (ITypeLib2
*) pTypeLibImpl
;
2589 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2595 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2596 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2597 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2598 ret
= SysAllocString(nameW
);
2599 HeapFree(GetProcessHeap(), 0, nameW
);
2603 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2609 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2610 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2614 guid
->Data4
[0] = s
>> 8;
2615 guid
->Data4
[1] = s
& 0xff;
2618 for(i
= 0; i
< 6; i
++) {
2619 memcpy(b
, str
+ 24 + 2 * i
, 2);
2620 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2625 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2632 bytelen
= *(WORD
*)ptr
;
2633 if(bytelen
== 0xffff) return 2;
2634 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2635 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2636 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2637 *pBstr
= SysAllocStringLen(nameW
, len
);
2638 HeapFree(GetProcessHeap(), 0, nameW
);
2642 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2647 bytelen
= *(WORD
*)ptr
;
2648 if(bytelen
== 0xffff) return 2;
2649 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2650 memcpy(*str
, ptr
+ 2, bytelen
);
2651 (*str
)[bytelen
] = '\0';
2655 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2657 char *ptr
= pLibBlk
;
2660 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2661 FIXME("libblk magic = %04x\n", w
);
2666 if((w
= *(WORD
*)ptr
) != 0xffff) {
2667 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2672 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2674 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2676 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2679 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2682 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
2683 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
2685 pTypeLibImpl
->LibAttr
.lcid
= 0;
2688 ptr
+= 4; /* skip res12 */
2690 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2693 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2696 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2699 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2700 ptr
+= sizeof(GUID
);
2702 return ptr
- (char*)pLibBlk
;
2705 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
)
2710 if((*pType
& 0xe00) == 0xe00) {
2712 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2714 pTD
= pTD
->u
.lptdesc
;
2716 switch(*pType
& 0x3f) {
2719 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2721 pTD
= pTD
->u
.lptdesc
;
2724 case VT_USERDEFINED
:
2725 pTD
->vt
= VT_USERDEFINED
;
2726 pTD
->u
.hreftype
= *(++pType
) / 4;
2732 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2735 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2737 pTD
->vt
= VT_CARRAY
;
2738 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2740 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2741 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2742 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2743 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2745 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2751 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2755 pTD
->vt
= VT_SAFEARRAY
;
2756 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2758 pTD
= pTD
->u
.lptdesc
;
2762 pTD
->vt
= *pType
& 0x3f;
2771 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2773 /* Handle [in/out] first */
2774 if((*pType
& 0xc000) == 0xc000)
2775 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2776 else if(*pType
& 0x8000)
2777 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2778 else if(*pType
& 0x4000)
2779 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2781 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2784 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2787 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2789 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
);
2793 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
2798 TLBRefType
*ref_type
;
2800 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2801 FIXME("Ref magic = %x\n", pRef
->magic
);
2804 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2806 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2808 unsigned int lib_offs
, type_num
;
2810 ref_type
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref_type
));
2812 name
+= SLTG_ReadStringA(name
, &refname
);
2813 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2814 FIXME("Can't sscanf ref\n");
2815 if(lib_offs
!= 0xffff) {
2816 TLBImpLib
**import
= &pTL
->pImpLibs
;
2819 if((*import
)->offset
== lib_offs
)
2821 import
= &(*import
)->next
;
2824 char fname
[MAX_PATH
+1];
2827 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2829 (*import
)->offset
= lib_offs
;
2830 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2832 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
2833 &(*import
)->wVersionMajor
,
2834 &(*import
)->wVersionMinor
,
2835 &(*import
)->lcid
, fname
) != 4) {
2836 FIXME("can't sscanf ref %s\n",
2837 pNameTable
+ lib_offs
+ 40);
2839 len
= strlen(fname
);
2840 if(fname
[len
-1] != '#')
2841 FIXME("fname = %s\n", fname
);
2842 fname
[len
-1] = '\0';
2843 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2845 ref_type
->pImpTLInfo
= *import
;
2847 /* Store a reference to IDispatch */
2848 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&(*import
)->guid
, &IID_StdOle
) && type_num
== 4)
2849 pTL
->dispatch_href
= ref
;
2851 } else { /* internal ref */
2852 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
2854 ref_type
->reference
= ref
;
2855 ref_type
->index
= type_num
;
2857 HeapFree(GetProcessHeap(), 0, refname
);
2858 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
2860 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2861 FIXME("End of ref block magic = %x\n", *name
);
2862 dump_TLBRefType(pTL
);
2865 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2868 SLTG_ImplInfo
*info
;
2869 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2870 /* I don't really get this structure, usually it's 0x16 bytes
2871 long, but iuser.tlb contains some that are 0x18 bytes long.
2872 That's ok because we can use the next ptr to jump to the next
2873 one. But how do we know the length of the last one? The WORD
2874 at offs 0x8 might be the clue. For now I'm just assuming that
2875 the last one is the regular 0x16 bytes. */
2877 info
= (SLTG_ImplInfo
*)pBlk
;
2879 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2880 sizeof(**ppImplType
));
2881 (*ppImplType
)->hRef
= info
->ref
;
2882 (*ppImplType
)->implflags
= info
->impltypeflags
;
2883 pTI
->TypeAttr
.cImplTypes
++;
2884 ppImplType
= &(*ppImplType
)->next
;
2886 if(info
->next
== 0xffff)
2889 FIXME("Interface inheriting more than one interface\n");
2890 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2892 info
++; /* see comment at top of function */
2896 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
, char *pNameTable
)
2898 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2899 BSTR bstrPrevName
= NULL
;
2900 SLTG_Variable
*pItem
;
2905 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
2906 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++) {
2908 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2909 sizeof(**ppVarDesc
));
2910 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2912 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
2913 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
2914 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
2918 if (pItem
->name
== 0xfffe)
2919 (*ppVarDesc
)->Name
= SysAllocString(bstrPrevName
);
2921 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2923 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
2924 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
2926 if (pItem
->flags
& 0x40) {
2927 TRACE_(typelib
)("VAR_DISPATCH\n");
2928 (*ppVarDesc
)->vardesc
.varkind
= VAR_DISPATCH
;
2930 else if (pItem
->flags
& 0x10) {
2931 TRACE_(typelib
)("VAR_CONST\n");
2932 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
2933 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
2935 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
2936 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
2937 *(INT
*)(pBlk
+ pItem
->byte_offs
);
2940 TRACE_(typelib
)("VAR_PERINSTANCE\n");
2941 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2942 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2945 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
2946 (*ppVarDesc
)->vardesc
.wVarFlags
= pItem
->varflags
;
2948 if (pItem
->flags
& 0x80)
2949 (*ppVarDesc
)->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
2951 if(pItem
->flags
& 0x02)
2952 pType
= &pItem
->type
;
2954 pType
= (WORD
*)(pBlk
+ pItem
->type
);
2956 if (pItem
->flags
& ~0xd2)
2957 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xd2);
2959 SLTG_DoElem(pType
, pBlk
,
2960 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2962 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2964 bstrPrevName
= (*ppVarDesc
)->Name
;
2965 ppVarDesc
= &((*ppVarDesc
)->next
);
2967 pTI
->TypeAttr
.cVars
= cVars
;
2970 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cFuncs
, char *pNameTable
)
2972 SLTG_Function
*pFunc
;
2974 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2976 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
;
2977 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++) {
2982 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2983 sizeof(**ppFuncDesc
));
2985 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
2986 case SLTG_FUNCTION_MAGIC
:
2987 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
2989 case SLTG_DISPATCH_FUNCTION_MAGIC
:
2990 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_DISPATCH
;
2992 case SLTG_STATIC_FUNCTION_MAGIC
:
2993 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_STATIC
;
2996 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
2997 HeapFree(GetProcessHeap(), 0, *ppFuncDesc
);
3001 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
3003 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
3004 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
3005 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
3006 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
3007 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
3008 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
3010 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
3011 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
3013 if(pFunc
->retnextopt
& 0x80)
3014 pType
= &pFunc
->rettype
;
3016 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
3018 SLTG_DoElem(pType
, pBlk
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
3020 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
3021 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3022 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
3023 (*ppFuncDesc
)->pParamDesc
=
3024 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3025 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
3027 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
3029 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
3030 char *paramName
= pNameTable
+ *pArg
;
3032 /* If arg type follows then paramName points to the 2nd
3033 letter of the name, else the next WORD is an offset to
3034 the arg type and paramName points to the first letter.
3035 So let's take one char off paramName and see if we're
3036 pointing at an alpha-numeric char. However if *pArg is
3037 0xffff or 0xfffe then the param has no name, the former
3038 meaning that the next WORD is the type, the latter
3039 meaning the the next WORD is an offset to the type. */
3044 else if(*pArg
== 0xfffe) {
3048 else if(paramName
[-1] && !isalnum(paramName
[-1]))
3053 if(HaveOffs
) { /* the next word is an offset to type */
3054 pType
= (WORD
*)(pBlk
+ *pArg
);
3055 SLTG_DoElem(pType
, pBlk
,
3056 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
3061 pArg
= SLTG_DoElem(pArg
, pBlk
,
3062 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
3065 /* Are we an optional param ? */
3066 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
3067 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
3068 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
3071 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
3072 TLB_MultiByteToBSTR(paramName
);
3076 ppFuncDesc
= &((*ppFuncDesc
)->next
);
3077 if(pFunc
->next
== 0xffff) break;
3079 pTI
->TypeAttr
.cFuncs
= cFuncs
;
3082 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
3083 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3084 SLTG_TypeInfoTail
*pTITail
)
3086 char *pFirstItem
, *pNextItem
;
3088 if(pTIHeader
->href_table
!= 0xffffffff) {
3089 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3093 pFirstItem
= pNextItem
= pBlk
;
3095 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3096 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
3101 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
3102 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3103 SLTG_TypeInfoTail
*pTITail
)
3105 char *pFirstItem
, *pNextItem
;
3107 if(pTIHeader
->href_table
!= 0xffffffff) {
3108 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3112 pFirstItem
= pNextItem
= pBlk
;
3114 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3115 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
3118 if (pTITail
->funcs_off
!= 0xffff)
3119 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
);
3121 if (TRACE_ON(typelib
))
3122 dump_TLBFuncDesc(pTI
->funclist
);
3125 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
3126 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3127 SLTG_TypeInfoTail
*pTITail
)
3129 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
);
3132 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3133 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3134 SLTG_TypeInfoTail
*pTITail
)
3138 if (pTITail
->simple_alias
) {
3139 /* if simple alias, no more processing required */
3140 pTI
->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3144 if(pTIHeader
->href_table
!= 0xffffffff) {
3145 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3149 /* otherwise it is an offset to a type */
3150 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
3152 SLTG_DoType(pType
, pBlk
, &pTI
->TypeAttr
.tdescAlias
);
3155 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3156 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3157 SLTG_TypeInfoTail
*pTITail
)
3159 if (pTIHeader
->href_table
!= 0xffffffff)
3160 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3163 if (pTITail
->vars_off
!= 0xffff)
3164 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
);
3166 if (pTITail
->funcs_off
!= 0xffff)
3167 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
);
3169 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3170 * of dispinterface functons including the IDispatch ones, so
3171 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3172 pTI
->TypeAttr
.cbSizeVft
= pTI
->TypeAttr
.cFuncs
* sizeof(void *);
3174 if (TRACE_ON(typelib
))
3175 dump_TLBFuncDesc(pTI
->funclist
);
3178 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3179 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3180 SLTG_TypeInfoTail
*pTITail
)
3182 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
);
3185 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
3186 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3187 SLTG_TypeInfoTail
*pTITail
)
3189 if (pTIHeader
->href_table
!= 0xffffffff)
3190 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3193 if (pTITail
->vars_off
!= 0xffff)
3194 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
);
3196 if (pTITail
->funcs_off
!= 0xffff)
3197 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
);
3200 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3201 managable copy of it into this */
3214 } SLTG_InternalOtherTypeInfo
;
3216 /****************************************************************************
3217 * ITypeLib2_Constructor_SLTG
3219 * loading a SLTG typelib from an in-memory image
3221 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3223 ITypeLibImpl
*pTypeLibImpl
;
3224 SLTG_Header
*pHeader
;
3225 SLTG_BlkEntry
*pBlkEntry
;
3229 LPVOID pBlk
, pFirstBlk
;
3230 SLTG_LibBlk
*pLibBlk
;
3231 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3232 char *pAfterOTIBlks
= NULL
;
3233 char *pNameTable
, *ptr
;
3236 ITypeInfoImpl
**ppTypeInfoImpl
;
3238 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3241 pTypeLibImpl
= TypeLibImpl_Constructor();
3242 if (!pTypeLibImpl
) return NULL
;
3246 TRACE_(typelib
)("header:\n");
3247 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
3248 pHeader
->nrOfFileBlks
);
3249 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3250 FIXME("Header type magic 0x%08x not supported.\n",
3251 pHeader
->SLTG_magic
);
3255 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3256 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3258 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3259 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3261 /* Next we have a magic block */
3262 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3264 /* Let's see if we're still in sync */
3265 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3266 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3267 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3270 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3271 sizeof(SLTG_DIR_MAGIC
))) {
3272 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
3276 pIndex
= (SLTG_Index
*)(pMagic
+1);
3278 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3280 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
3282 /* We'll set up a ptr to the main library block, which is the last one. */
3284 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3285 pBlkEntry
[order
].next
!= 0;
3286 order
= pBlkEntry
[order
].next
- 1, i
++) {
3287 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3291 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3293 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3298 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3300 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3301 sizeof(*pOtherTypeInfoBlks
) *
3302 pTypeLibImpl
->TypeInfoCount
);
3305 ptr
= (char*)pLibBlk
+ len
;
3307 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3311 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3313 w
= *(WORD
*)(ptr
+ 2);
3316 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3318 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3319 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3321 w
= *(WORD
*)(ptr
+ 4 + len
);
3323 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3325 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3327 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3328 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3330 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3331 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3332 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3334 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3336 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3339 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3340 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3341 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3342 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3343 len
+= sizeof(SLTG_OtherTypeInfo
);
3347 pAfterOTIBlks
= ptr
;
3349 /* Skip this WORD and get the next DWORD */
3350 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3352 /* Now add this to pLibBLk look at what we're pointing at and
3353 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3354 dust and we should be pointing at the beginning of the name
3357 pNameTable
= (char*)pLibBlk
+ len
;
3359 switch(*(WORD
*)pNameTable
) {
3366 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3370 pNameTable
+= 0x216;
3374 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3376 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3379 /* Hopefully we now have enough ptrs set up to actually read in
3380 some TypeInfos. It's not clear which order to do them in, so
3381 I'll just follow the links along the BlkEntry chain and read
3382 them in the order in which they are in the file */
3384 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3386 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3387 pBlkEntry
[order
].next
!= 0;
3388 order
= pBlkEntry
[order
].next
- 1, i
++) {
3390 SLTG_TypeInfoHeader
*pTIHeader
;
3391 SLTG_TypeInfoTail
*pTITail
;
3392 SLTG_MemberHeader
*pMemHeader
;
3394 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3395 pOtherTypeInfoBlks
[i
].index_name
)) {
3396 FIXME("Index strings don't match\n");
3401 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3402 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3405 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3406 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
3408 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3409 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3410 (*ppTypeInfoImpl
)->index
= i
;
3411 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3412 pOtherTypeInfoBlks
[i
].name_offs
+
3414 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3415 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3417 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3418 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3419 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3420 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3421 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3423 if((pTIHeader
->typeflags1
& 7) != 2)
3424 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3425 if(pTIHeader
->typeflags3
!= 2)
3426 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3428 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3429 debugstr_w((*ppTypeInfoImpl
)->Name
),
3430 typekind_desc
[pTIHeader
->typekind
],
3431 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3432 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3434 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
3436 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
3438 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3439 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3440 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3442 switch(pTIHeader
->typekind
) {
3444 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3445 pTIHeader
, pTITail
);
3449 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3450 pTIHeader
, pTITail
);
3453 case TKIND_INTERFACE
:
3454 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3455 pTIHeader
, pTITail
);
3459 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3460 pTIHeader
, pTITail
);
3464 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3465 pTIHeader
, pTITail
);
3468 case TKIND_DISPATCH
:
3469 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3470 pTIHeader
, pTITail
);
3474 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3475 pTIHeader
, pTITail
);
3479 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3484 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3485 but we've already set those */
3486 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3501 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3502 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3505 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3506 FIXME("Somehow processed %d TypeInfos\n", i
);
3510 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3511 return (ITypeLib2
*)pTypeLibImpl
;
3514 /* ITypeLib::QueryInterface
3516 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3521 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3523 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3526 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3527 IsEqualIID(riid
,&IID_ITypeLib
)||
3528 IsEqualIID(riid
,&IID_ITypeLib2
))
3535 ITypeLib2_AddRef(iface
);
3536 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3539 TRACE("-- Interface: E_NOINTERFACE\n");
3540 return E_NOINTERFACE
;
3545 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3547 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3548 ULONG ref
= InterlockedIncrement(&This
->ref
);
3550 TRACE("(%p)->ref was %u\n",This
, ref
- 1);
3555 /* ITypeLib::Release
3557 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3559 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3560 ULONG ref
= InterlockedDecrement(&This
->ref
);
3562 TRACE("(%p)->(%u)\n",This
, ref
);
3566 TLBImpLib
*pImpLib
, *pImpLibNext
;
3567 TLBCustData
*pCustData
, *pCustDataNext
;
3568 TLBRefType
*ref_type
;
3572 /* remove cache entry */
3575 TRACE("removing from cache list\n");
3576 EnterCriticalSection(&cache_section
);
3577 if (This
->next
) This
->next
->prev
= This
->prev
;
3578 if (This
->prev
) This
->prev
->next
= This
->next
;
3579 else tlb_cache_first
= This
->next
;
3580 LeaveCriticalSection(&cache_section
);
3581 HeapFree(GetProcessHeap(), 0, This
->path
);
3583 TRACE(" destroying ITypeLib(%p)\n",This
);
3587 SysFreeString(This
->Name
);
3591 if (This
->DocString
)
3593 SysFreeString(This
->DocString
);
3594 This
->DocString
= NULL
;
3599 SysFreeString(This
->HelpFile
);
3600 This
->HelpFile
= NULL
;
3603 if (This
->HelpStringDll
)
3605 SysFreeString(This
->HelpStringDll
);
3606 This
->HelpStringDll
= NULL
;
3609 for (pCustData
= This
->pCustData
; pCustData
; pCustData
= pCustDataNext
)
3611 VariantClear(&pCustData
->data
);
3613 pCustDataNext
= pCustData
->next
;
3614 TLB_Free(pCustData
);
3617 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
3618 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
3619 TLB_Free(This
->pTypeDesc
[i
].u
.lpadesc
);
3621 TLB_Free(This
->pTypeDesc
);
3623 for (pImpLib
= This
->pImpLibs
; pImpLib
; pImpLib
= pImpLibNext
)
3625 if (pImpLib
->pImpTypeLib
)
3626 ITypeLib_Release((ITypeLib
*)pImpLib
->pImpTypeLib
);
3627 TLB_Free(pImpLib
->name
);
3629 pImpLibNext
= pImpLib
->next
;
3633 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
3635 list_remove(&ref_type
->entry
);
3639 if (This
->pTypeInfo
) /* can be NULL */
3640 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3641 HeapFree(GetProcessHeap(),0,This
);
3648 /* ITypeLib::GetTypeInfoCount
3650 * Returns the number of type descriptions in the type library
3652 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3654 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3655 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3656 return This
->TypeInfoCount
;
3659 /* ITypeLib::GetTypeInfo
3661 * retrieves the specified type description in the library.
3663 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3666 ITypeInfo
**ppTInfo
)
3670 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3671 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3673 TRACE("(%p)->(index=%d)\n", This
, index
);
3675 if (!ppTInfo
) return E_INVALIDARG
;
3677 /* search element n in list */
3678 for(i
=0; i
< index
; i
++)
3680 pTypeInfo
= pTypeInfo
->next
;
3683 TRACE("-- element not found\n");
3684 return TYPE_E_ELEMENTNOTFOUND
;
3688 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3690 ITypeInfo_AddRef(*ppTInfo
);
3691 TRACE("-- found (%p)\n",*ppTInfo
);
3696 /* ITypeLibs::GetTypeInfoType
3698 * Retrieves the type of a type description.
3700 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3705 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3707 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3709 if ((ITypeLib2_fnGetTypeInfoCount(iface
) < index
+ 1) || (index
< 0))
3710 return TYPE_E_ELEMENTNOTFOUND
;
3712 TRACE("(%p) index %d\n", This
, index
);
3714 if(!pTKind
) return E_INVALIDARG
;
3716 /* search element n in list */
3717 for(i
=0; i
< index
; i
++)
3721 TRACE("-- element not found\n");
3722 return TYPE_E_ELEMENTNOTFOUND
;
3724 pTInfo
= pTInfo
->next
;
3727 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3728 TRACE("-- found Type (%d)\n", *pTKind
);
3732 /* ITypeLib::GetTypeInfoOfGuid
3734 * Retrieves the type description that corresponds to the specified GUID.
3737 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3740 ITypeInfo
**ppTInfo
)
3742 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3743 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3745 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3749 WARN("-- element not found\n");
3750 return TYPE_E_ELEMENTNOTFOUND
;
3753 /* search linked list for guid */
3754 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3756 pTypeInfo
= pTypeInfo
->next
;
3760 /* end of list reached */
3761 WARN("-- element not found\n");
3762 return TYPE_E_ELEMENTNOTFOUND
;
3766 TRACE("-- found (%p, %s)\n",
3768 debugstr_w(pTypeInfo
->Name
));
3770 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3771 ITypeInfo_AddRef(*ppTInfo
);
3775 /* ITypeLib::GetLibAttr
3777 * Retrieves the structure that contains the library's attributes.
3780 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3782 LPTLIBATTR
*ppTLibAttr
)
3784 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3785 TRACE("(%p)\n",This
);
3786 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3787 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3791 /* ITypeLib::GetTypeComp
3793 * Enables a client compiler to bind to a library's types, variables,
3794 * constants, and global functions.
3797 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3799 ITypeComp
**ppTComp
)
3801 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3803 TRACE("(%p)->(%p)\n",This
,ppTComp
);
3804 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
3805 ITypeComp_AddRef(*ppTComp
);
3810 /* ITypeLib::GetDocumentation
3812 * Retrieves the library's documentation string, the complete Help file name
3813 * and path, and the context identifier for the library Help topic in the Help
3816 * On a successful return all non-null BSTR pointers will have been set,
3819 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3823 BSTR
*pBstrDocString
,
3824 DWORD
*pdwHelpContext
,
3825 BSTR
*pBstrHelpFile
)
3827 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3829 HRESULT result
= E_INVALIDARG
;
3834 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3836 pBstrName
, pBstrDocString
,
3837 pdwHelpContext
, pBstrHelpFile
);
3841 /* documentation for the typelib */
3846 if(!(*pBstrName
= SysAllocString(This
->Name
)))
3854 if (This
->DocString
)
3856 if(!(*pBstrDocString
= SysAllocString(This
->DocString
)))
3859 else if (This
->Name
)
3861 if(!(*pBstrDocString
= SysAllocString(This
->Name
)))
3865 *pBstrDocString
= NULL
;
3869 *pdwHelpContext
= This
->dwHelpContext
;
3875 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
)))
3879 *pBstrHelpFile
= NULL
;
3886 /* for a typeinfo */
3887 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3889 if(SUCCEEDED(result
))
3891 result
= ITypeInfo_GetDocumentation(pTInfo
,
3895 pdwHelpContext
, pBstrHelpFile
);
3897 ITypeInfo_Release(pTInfo
);
3902 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3904 if (pBstrName
) SysFreeString (*pBstrName
);
3906 return STG_E_INSUFFICIENTMEMORY
;
3911 * Indicates whether a passed-in string contains the name of a type or member
3912 * described in the library.
3915 static HRESULT WINAPI
ITypeLib2_fnIsName(
3921 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3922 ITypeInfoImpl
*pTInfo
;
3923 TLBFuncDesc
*pFInfo
;
3926 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
3928 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3932 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3933 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3934 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3935 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3936 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3937 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3938 goto ITypeLib2_fnIsName_exit
;
3940 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3941 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3946 ITypeLib2_fnIsName_exit
:
3947 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3948 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3953 /* ITypeLib::FindName
3955 * Finds occurrences of a type description in a type library. This may be used
3956 * to quickly verify that a name exists in a type library.
3959 static HRESULT WINAPI
ITypeLib2_fnFindName(
3963 ITypeInfo
**ppTInfo
,
3967 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3968 ITypeInfoImpl
*pTInfo
;
3969 TLBFuncDesc
*pFInfo
;
3972 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
3974 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3975 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3976 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3977 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3978 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++) {
3979 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3980 goto ITypeLib2_fnFindName_exit
;
3983 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3984 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3986 ITypeLib2_fnFindName_exit
:
3987 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3988 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3991 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3992 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3999 /* ITypeLib::ReleaseTLibAttr
4001 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4004 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
4006 TLIBATTR
*pTLibAttr
)
4008 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4009 TRACE("freeing (%p)\n",This
);
4010 HeapFree(GetProcessHeap(),0,pTLibAttr
);
4014 /* ITypeLib2::GetCustData
4016 * gets the custom data
4018 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
4023 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4024 TLBCustData
*pCData
;
4026 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
4028 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4031 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4035 VariantInit( pVarVal
);
4036 VariantCopy( pVarVal
, &pCData
->data
);
4039 return E_INVALIDARG
; /* FIXME: correct? */
4042 /* ITypeLib2::GetLibStatistics
4044 * Returns statistics about a type library that are required for efficient
4045 * sizing of hash tables.
4048 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
4050 ULONG
*pcUniqueNames
,
4051 ULONG
*pcchUniqueNames
)
4053 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4055 FIXME("(%p): stub!\n", This
);
4057 if(pcUniqueNames
) *pcUniqueNames
=1;
4058 if(pcchUniqueNames
) *pcchUniqueNames
=1;
4062 /* ITypeLib2::GetDocumentation2
4064 * Retrieves the library's documentation string, the complete Help file name
4065 * and path, the localization context to use, and the context ID for the
4066 * library Help topic in the Help file.
4069 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
4073 BSTR
*pbstrHelpString
,
4074 DWORD
*pdwHelpStringContext
,
4075 BSTR
*pbstrHelpStringDll
)
4077 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4081 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
4083 /* the help string should be obtained from the helpstringdll,
4084 * using the _DLLGetDocumentation function, based on the supplied
4085 * lcid. Nice to do sometime...
4089 /* documentation for the typelib */
4091 *pbstrHelpString
=SysAllocString(This
->DocString
);
4092 if(pdwHelpStringContext
)
4093 *pdwHelpStringContext
=This
->dwHelpContext
;
4094 if(pbstrHelpStringDll
)
4095 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
4101 /* for a typeinfo */
4102 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
4104 if(SUCCEEDED(result
))
4106 ITypeInfo2
* pTInfo2
;
4107 result
= ITypeInfo_QueryInterface(pTInfo
,
4109 (LPVOID
*) &pTInfo2
);
4111 if(SUCCEEDED(result
))
4113 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
4117 pdwHelpStringContext
,
4118 pbstrHelpStringDll
);
4120 ITypeInfo2_Release(pTInfo2
);
4123 ITypeInfo_Release(pTInfo
);
4129 /* ITypeLib2::GetAllCustData
4131 * Gets all custom data items for the library.
4134 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
4136 CUSTDATA
*pCustData
)
4138 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4139 TLBCustData
*pCData
;
4141 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
4142 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
4143 if(pCustData
->prgCustData
){
4144 pCustData
->cCustData
=This
->ctCustData
;
4145 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
4146 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4147 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
4150 ERR(" OUT OF MEMORY!\n");
4151 return E_OUTOFMEMORY
;
4156 static const ITypeLib2Vtbl tlbvt
= {
4157 ITypeLib2_fnQueryInterface
,
4159 ITypeLib2_fnRelease
,
4160 ITypeLib2_fnGetTypeInfoCount
,
4161 ITypeLib2_fnGetTypeInfo
,
4162 ITypeLib2_fnGetTypeInfoType
,
4163 ITypeLib2_fnGetTypeInfoOfGuid
,
4164 ITypeLib2_fnGetLibAttr
,
4165 ITypeLib2_fnGetTypeComp
,
4166 ITypeLib2_fnGetDocumentation
,
4168 ITypeLib2_fnFindName
,
4169 ITypeLib2_fnReleaseTLibAttr
,
4171 ITypeLib2_fnGetCustData
,
4172 ITypeLib2_fnGetLibStatistics
,
4173 ITypeLib2_fnGetDocumentation2
,
4174 ITypeLib2_fnGetAllCustData
4178 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4180 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4182 return ITypeLib2_QueryInterface((ITypeLib
*)This
, riid
, ppv
);
4185 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4187 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4189 return ITypeLib2_AddRef((ITypeLib2
*)This
);
4192 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4194 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4196 return ITypeLib2_Release((ITypeLib2
*)This
);
4199 static HRESULT WINAPI
ITypeLibComp_fnBind(
4204 ITypeInfo
** ppTInfo
,
4205 DESCKIND
* pDescKind
,
4208 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4209 ITypeInfoImpl
*pTypeInfo
;
4211 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4213 *pDescKind
= DESCKIND_NONE
;
4214 pBindPtr
->lptcomp
= NULL
;
4217 for (pTypeInfo
= This
->pTypeInfo
; pTypeInfo
; pTypeInfo
= pTypeInfo
->next
)
4219 TRACE("testing %s\n", debugstr_w(pTypeInfo
->Name
));
4221 /* FIXME: check wFlags here? */
4222 /* FIXME: we should use a hash table to look this info up using lHash
4223 * instead of an O(n) search */
4224 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
) ||
4225 (pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
))
4227 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
, szName
))
4229 *pDescKind
= DESCKIND_TYPECOMP
;
4230 pBindPtr
->lptcomp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4231 ITypeComp_AddRef(pBindPtr
->lptcomp
);
4232 TRACE("module or enum: %s\n", debugstr_w(szName
));
4237 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
) ||
4238 (pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
))
4240 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4243 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4244 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
4246 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
4251 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_COCLASS
) &&
4252 (pTypeInfo
->TypeAttr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
4254 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4256 ITypeInfo
*subtypeinfo
;
4258 DESCKIND subdesckind
;
4260 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
4261 &subtypeinfo
, &subdesckind
, &subbindptr
);
4262 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
4264 TYPEDESC tdesc_appobject
=
4267 (TYPEDESC
*)pTypeInfo
->hreftype
4271 const VARDESC vardesc_appobject
=
4274 NULL
, /* lpstrSchema */
4289 VAR_STATIC
/* varkind */
4292 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
4294 /* cleanup things filled in by Bind call so we can put our
4295 * application object data in there instead */
4296 switch (subdesckind
)
4298 case DESCKIND_FUNCDESC
:
4299 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
4301 case DESCKIND_VARDESC
:
4302 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
4307 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
4309 if (pTypeInfo
->hreftype
== -1)
4310 FIXME("no hreftype for interface %p\n", pTypeInfo
);
4312 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
4316 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
4317 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
4318 ITypeInfo_AddRef(*ppTInfo
);
4324 TRACE("name not found %s\n", debugstr_w(szName
));
4328 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4332 ITypeInfo
** ppTInfo
,
4333 ITypeComp
** ppTComp
)
4335 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4339 static const ITypeCompVtbl tlbtcvt
=
4342 ITypeLibComp_fnQueryInterface
,
4343 ITypeLibComp_fnAddRef
,
4344 ITypeLibComp_fnRelease
,
4346 ITypeLibComp_fnBind
,
4347 ITypeLibComp_fnBindType
4350 /*================== ITypeInfo(2) Methods ===================================*/
4351 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
4353 ITypeInfoImpl
* pTypeInfoImpl
;
4355 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4358 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4359 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4360 pTypeInfoImpl
->ref
=1;
4361 pTypeInfoImpl
->hreftype
= -1;
4362 pTypeInfoImpl
->TypeAttr
.memidConstructor
= MEMBERID_NIL
;
4363 pTypeInfoImpl
->TypeAttr
.memidDestructor
= MEMBERID_NIL
;
4365 TRACE("(%p)\n", pTypeInfoImpl
);
4366 return (ITypeInfo2
*) pTypeInfoImpl
;
4369 /* ITypeInfo::QueryInterface
4371 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4376 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4378 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4381 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4382 IsEqualIID(riid
,&IID_ITypeInfo
)||
4383 IsEqualIID(riid
,&IID_ITypeInfo2
))
4387 ITypeInfo_AddRef(iface
);
4388 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4391 TRACE("-- Interface: E_NOINTERFACE\n");
4392 return E_NOINTERFACE
;
4395 /* ITypeInfo::AddRef
4397 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4399 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4400 ULONG ref
= InterlockedIncrement(&This
->ref
);
4402 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4404 TRACE("(%p)->ref is %u\n",This
, ref
);
4408 /* ITypeInfo::Release
4410 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
4412 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4413 ULONG ref
= InterlockedDecrement(&This
->ref
);
4415 TRACE("(%p)->(%u)\n",This
, ref
);
4418 /* We don't release ITypeLib when ref=0 because
4419 it means that function is called by ITypeLib2_Release */
4420 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
4422 TLBFuncDesc
*pFInfo
, *pFInfoNext
;
4423 TLBVarDesc
*pVInfo
, *pVInfoNext
;
4424 TLBImplType
*pImpl
, *pImplNext
;
4425 TLBCustData
*pCustData
, *pCustDataNext
;
4427 TRACE("destroying ITypeInfo(%p)\n",This
);
4429 if (This
->no_free_data
)
4434 SysFreeString(This
->Name
);
4438 if (This
->DocString
)
4440 SysFreeString(This
->DocString
);
4441 This
->DocString
= 0;
4446 SysFreeString(This
->DllName
);
4450 for (pFInfo
= This
->funclist
; pFInfo
; pFInfo
= pFInfoNext
)
4453 for(i
= 0;i
< pFInfo
->funcdesc
.cParams
; i
++)
4455 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[i
];
4456 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4458 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
4459 TLB_Free(elemdesc
->u
.paramdesc
.pparamdescex
);
4461 SysFreeString(pFInfo
->pParamDesc
[i
].Name
);
4463 TLB_Free(pFInfo
->funcdesc
.lprgelemdescParam
);
4464 TLB_Free(pFInfo
->pParamDesc
);
4465 for (pCustData
= This
->pCustData
; pCustData
; pCustData
= pCustDataNext
)
4467 VariantClear(&pCustData
->data
);
4469 pCustDataNext
= pCustData
->next
;
4470 TLB_Free(pCustData
);
4472 if (HIWORD(pFInfo
->Entry
) != 0 && pFInfo
->Entry
!= (BSTR
)-1)
4473 SysFreeString(pFInfo
->Entry
);
4474 SysFreeString(pFInfo
->HelpString
);
4475 SysFreeString(pFInfo
->Name
);
4477 pFInfoNext
= pFInfo
->next
;
4480 for (pVInfo
= This
->varlist
; pVInfo
; pVInfo
= pVInfoNext
)
4482 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
4484 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
4485 TLB_Free(pVInfo
->vardesc
.u
.lpvarValue
);
4487 SysFreeString(pVInfo
->Name
);
4488 pVInfoNext
= pVInfo
->next
;
4491 for(pImpl
= This
->impltypelist
; pImpl
; pImpl
= pImplNext
)
4493 for (pCustData
= pImpl
->pCustData
; pCustData
; pCustData
= pCustDataNext
)
4495 VariantClear(&pCustData
->data
);
4497 pCustDataNext
= pCustData
->next
;
4498 TLB_Free(pCustData
);
4500 pImplNext
= pImpl
->next
;
4503 TLB_Free(This
->pCustData
);
4508 ITypeInfo_Release((ITypeInfo
*)This
->next
);
4511 HeapFree(GetProcessHeap(),0,This
);
4517 /* ITypeInfo::GetTypeAttr
4519 * Retrieves a TYPEATTR structure that contains the attributes of the type
4523 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
4524 LPTYPEATTR
*ppTypeAttr
)
4526 const ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4529 TRACE("(%p)\n",This
);
4531 size
= sizeof(**ppTypeAttr
);
4532 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
4533 size
+= TLB_SizeTypeDesc(&This
->TypeAttr
.tdescAlias
, FALSE
);
4535 *ppTypeAttr
= HeapAlloc(GetProcessHeap(), 0, size
);
4537 return E_OUTOFMEMORY
;
4539 memcpy(*ppTypeAttr
, &This
->TypeAttr
, sizeof(**ppTypeAttr
));
4541 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
4542 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
4543 &This
->TypeAttr
.tdescAlias
, (void *)(*ppTypeAttr
+ 1));
4545 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
4546 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ 4; /* This should include all the inherited
4548 (*ppTypeAttr
)->cbSizeVft
= 28; /* This is always the size of IDispatch's vtbl */
4549 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
4554 /* ITypeInfo::GetTypeComp
4556 * Retrieves the ITypeComp interface for the type description, which enables a
4557 * client compiler to bind to the type description's members.
4560 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
4561 ITypeComp
* *ppTComp
)
4563 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4565 TRACE("(%p)->(%p)\n", This
, ppTComp
);
4567 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4568 ITypeComp_AddRef(*ppTComp
);
4572 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
4574 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
4575 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4576 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
4580 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
4582 memcpy(dest
, src
, sizeof(ELEMDESC
));
4583 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
4584 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4586 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
4587 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
4588 *buffer
+= sizeof(PARAMDESCEX
);
4589 memcpy(pparamdescex_dest
, pparamdescex_src
, sizeof(PARAMDESCEX
));
4590 VariantInit(&pparamdescex_dest
->varDefaultValue
);
4591 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
4592 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
4595 dest
->u
.paramdesc
.pparamdescex
= NULL
;
4599 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
4601 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4602 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
4605 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
4609 SIZE_T size
= sizeof(*src
);
4613 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
4614 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
4615 for (i
= 0; i
< src
->cParams
; i
++)
4617 size
+= sizeof(ELEMDESC
);
4618 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
4621 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
4622 if (!dest
) return E_OUTOFMEMORY
;
4624 memcpy(dest
, src
, sizeof(FUNCDESC
));
4625 buffer
= (char *)(dest
+ 1);
4627 dest
->lprgscode
= (SCODE
*)buffer
;
4628 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
4629 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
4631 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
4634 SysFreeString((BSTR
)dest
);
4638 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
4639 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
4640 for (i
= 0; i
< src
->cParams
; i
++)
4642 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
4648 /* undo the above actions */
4649 for (i
= i
- 1; i
>= 0; i
--)
4650 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
4651 TLB_FreeElemDesc(&dest
->elemdescFunc
);
4652 SysFreeString((BSTR
)dest
);
4656 /* special treatment for dispinterfaces: this makes functions appear
4657 * to return their [retval] value when it is really returning an
4659 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
4661 if (dest
->cParams
&&
4662 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
4664 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
4665 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
4667 ERR("elemdesc should have started with VT_PTR instead of:\n");
4669 dump_ELEMDESC(elemdesc
);
4670 return E_UNEXPECTED
;
4673 /* copy last parameter to the return value. we are using a flat
4674 * buffer so there is no danger of leaking memory in
4676 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
4678 /* remove the last parameter */
4682 /* otherwise this function is made to appear to have no return
4684 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
4692 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
4694 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4695 const TLBFuncDesc
*pFDesc
;
4698 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
4703 *ppFuncDesc
= &pFDesc
->funcdesc
;
4707 return TYPE_E_ELEMENTNOTFOUND
;
4710 /* internal function to make the inherited interfaces' methods appear
4711 * part of the interface */
4712 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
4713 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
)
4715 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4717 UINT implemented_funcs
= 0;
4722 if(This
->impltypelist
)
4724 ITypeInfo
*pSubTypeInfo
;
4727 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pSubTypeInfo
);
4731 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
4735 implemented_funcs
+= sub_funcs
;
4736 ITypeInfo_Release(pSubTypeInfo
);
4742 *funcs
= implemented_funcs
+ This
->TypeAttr
.cFuncs
;
4744 if (index
< implemented_funcs
)
4745 return E_INVALIDARG
;
4746 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
4750 /* ITypeInfo::GetFuncDesc
4752 * Retrieves the FUNCDESC structure that contains information about a
4753 * specified function.
4756 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
4757 LPFUNCDESC
*ppFuncDesc
)
4759 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4760 const FUNCDESC
*internal_funcdesc
;
4763 TRACE("(%p) index %d\n", This
, index
);
4765 if (This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
4766 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
4767 &internal_funcdesc
, NULL
);
4769 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
4770 &internal_funcdesc
);
4773 WARN("description for function %d not found\n", index
);
4777 return TLB_AllocAndInitFuncDesc(
4780 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
4783 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
4787 SIZE_T size
= sizeof(*src
);
4790 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
4791 if (src
->varkind
== VAR_CONST
)
4792 size
+= sizeof(VARIANT
);
4793 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
4795 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
4796 if (!dest
) return E_OUTOFMEMORY
;
4799 buffer
= (char *)(dest
+ 1);
4800 if (src
->lpstrSchema
)
4803 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
4804 len
= strlenW(src
->lpstrSchema
);
4805 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
4806 buffer
+= (len
+ 1) * sizeof(WCHAR
);
4809 if (src
->varkind
== VAR_CONST
)
4813 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
4814 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
4815 buffer
+= sizeof(VARIANT
);
4816 VariantInit(dest
->u
.lpvarValue
);
4817 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
4820 SysFreeString((BSTR
)dest_ptr
);
4824 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
4827 if (src
->varkind
== VAR_CONST
)
4828 VariantClear(dest
->u
.lpvarValue
);
4829 SysFreeString((BSTR
)dest
);
4836 /* ITypeInfo::GetVarDesc
4838 * Retrieves a VARDESC structure that describes the specified variable.
4841 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
4842 LPVARDESC
*ppVarDesc
)
4844 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4846 const TLBVarDesc
*pVDesc
;
4848 TRACE("(%p) index %d\n", This
, index
);
4850 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
4854 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
4856 return E_INVALIDARG
;
4859 /* ITypeInfo_GetNames
4861 * Retrieves the variable with the specified member ID (or the name of the
4862 * property or method and its parameters) that correspond to the specified
4865 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
4866 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
4868 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4869 const TLBFuncDesc
*pFDesc
;
4870 const TLBVarDesc
*pVDesc
;
4872 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
4873 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
4876 /* function found, now return function and parameter names */
4877 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
4880 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
4882 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
4888 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
4891 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
4896 if(This
->impltypelist
&&
4897 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4898 /* recursive search */
4901 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
4903 if(SUCCEEDED(result
))
4905 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
4906 ITypeInfo_Release(pTInfo
);
4909 WARN("Could not search inherited interface!\n");
4913 WARN("no names found\n");
4916 return TYPE_E_ELEMENTNOTFOUND
;
4923 /* ITypeInfo::GetRefTypeOfImplType
4925 * If a type description describes a COM class, it retrieves the type
4926 * description of the implemented interface types. For an interface,
4927 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4931 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
4936 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4939 const TLBImplType
*pImpl
= This
->impltypelist
;
4941 TRACE("(%p) index %d\n", This
, index
);
4942 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
4946 /* only valid on dual interfaces;
4947 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4949 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
4951 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
4952 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4958 hr
= TYPE_E_ELEMENTNOTFOUND
;
4961 else if(index
== 0 && This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
4963 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
4964 *pRefType
= This
->pTypeLib
->dispatch_href
;
4968 /* get element n from linked list */
4969 for(i
=0; pImpl
&& i
<index
; i
++)
4971 pImpl
= pImpl
->next
;
4975 *pRefType
= pImpl
->hRef
;
4977 hr
= TYPE_E_ELEMENTNOTFOUND
;
4983 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
4985 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
4991 /* ITypeInfo::GetImplTypeFlags
4993 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4994 * or base interface in a type description.
4996 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
4997 UINT index
, INT
*pImplTypeFlags
)
4999 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5003 TRACE("(%p) index %d\n", This
, index
);
5004 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
5005 i
++, pImpl
=pImpl
->next
)
5007 if(i
==index
&& pImpl
){
5008 *pImplTypeFlags
=pImpl
->implflags
;
5012 return TYPE_E_ELEMENTNOTFOUND
;
5016 * Maps between member names and member IDs, and parameter names and
5019 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
5020 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
5022 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5023 const TLBFuncDesc
*pFDesc
;
5024 const TLBVarDesc
*pVDesc
;
5028 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
5031 /* init out parameters in case of failure */
5032 for (i
= 0; i
< cNames
; i
++)
5033 pMemId
[i
] = MEMBERID_NIL
;
5035 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
5037 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
5038 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
5039 for(i
=1; i
< cNames
; i
++){
5040 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
5041 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
5043 if( j
<pFDesc
->funcdesc
.cParams
)
5046 ret
=DISP_E_UNKNOWNNAME
;
5048 TRACE("-- 0x%08x\n", ret
);
5052 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
5053 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
5054 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
5058 /* not found, see if it can be found in an inherited interface */
5059 if(This
->impltypelist
) {
5060 /* recursive search */
5062 ret
=ITypeInfo_GetRefTypeInfo(iface
,
5063 This
->impltypelist
->hRef
, &pTInfo
);
5065 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
5066 ITypeInfo_Release(pTInfo
);
5069 WARN("Could not search inherited interface!\n");
5071 WARN("no names found\n");
5072 return DISP_E_UNKNOWNNAME
;
5075 /* ITypeInfo::Invoke
5077 * Invokes a method, or accesses a property of an object, that implements the
5078 * interface described by the type description.
5081 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
5084 if (TRACE_ON(ole
)) {
5086 TRACE("Calling %p(",func
);
5087 for (i
=0;i
<nrargs
;i
++) TRACE("%08x,",args
[i
]);
5099 res
= func(args
[0]);
5102 res
= func(args
[0],args
[1]);
5105 res
= func(args
[0],args
[1],args
[2]);
5108 res
= func(args
[0],args
[1],args
[2],args
[3]);
5111 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
5114 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
5117 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
5120 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
5123 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
5126 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9]);
5129 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10]);
5132 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]);
5135 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]);
5138 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]);
5141 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]);
5144 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]);
5147 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]);
5150 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]);
5153 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]);
5156 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]);
5159 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]);
5162 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]);
5165 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]);
5168 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
5174 FIXME("unsupported calling convention %d\n",callconv
);
5178 TRACE("returns %08x\n",res
);
5182 extern int _argsize(DWORD vt
);
5184 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5187 ITypeInfo
*tinfo2
= NULL
;
5188 TYPEATTR
*tattr
= NULL
;
5190 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
5193 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5195 tdesc
->u
.hreftype
, hr
);
5198 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
5201 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
5202 ITypeInfo_Release(tinfo2
);
5206 switch (tattr
->typekind
)
5213 tdesc
= &tattr
->tdescAlias
;
5214 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
5217 case TKIND_INTERFACE
:
5218 if (IsEqualIID(&IID_IDispatch
, &tattr
->guid
))
5224 case TKIND_DISPATCH
:
5233 FIXME("TKIND_RECORD unhandled.\n");
5238 FIXME("TKIND_UNION unhandled.\n");
5243 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
5247 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
5248 ITypeInfo_Release(tinfo2
);
5252 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5256 /* enforce only one level of pointer indirection */
5257 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
5259 tdesc
= tdesc
->u
.lptdesc
;
5261 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5262 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5263 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5264 if ((tdesc
->vt
== VT_USERDEFINED
) ||
5265 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
5267 VARTYPE vt_userdefined
= 0;
5268 const TYPEDESC
*tdesc_userdefined
= tdesc
;
5269 if (tdesc
->vt
== VT_PTR
)
5271 vt_userdefined
= VT_BYREF
;
5272 tdesc_userdefined
= tdesc
->u
.lptdesc
;
5274 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
5276 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
5277 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
5279 *vt
|= vt_userdefined
;
5291 case VT_USERDEFINED
:
5292 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
5299 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
5300 hr
= DISP_E_BADVARTYPE
;
5304 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
5313 /***********************************************************************
5314 * DispCallFunc (OLEAUT32.@)
5316 * Invokes a function of the specifed calling convention, passing the
5317 * specified arguments and returns the result.
5320 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5321 * oVft [I] The offset in the vtable. See notes.
5322 * cc [I] Calling convention of the function to call.
5323 * vtReturn [I] The return type of the function.
5324 * cActuals [I] Number of parameters.
5325 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5326 * prgpvarg [I] The arguments to pass.
5327 * pvargResult [O] The return value of the function. Can be NULL.
5331 * Failure: HRESULT code.
5334 * The HRESULT return value of this function is not affected by the return
5335 * value of the user supplied function, which is returned in pvargResult.
5337 * If pvInstance is NULL then a non-object function is to be called and oVft
5338 * is the address of the function to call.
5340 * The cc parameter can be one of the following values:
5353 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
5354 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
5356 int i
, argsize
, argspos
;
5360 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5361 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
5362 pvargResult
, V_VT(pvargResult
));
5366 argsize
++; /* for This pointer */
5368 for (i
=0;i
<cActuals
;i
++)
5370 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
5371 dump_Variant(prgpvarg
[i
]);
5372 argsize
+= _argsize(prgvt
[i
]);
5374 args
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
5379 args
[0] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
5383 for (i
=0;i
<cActuals
;i
++)
5385 VARIANT
*arg
= prgpvarg
[i
];
5386 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
5387 if (prgvt
[i
] == VT_VARIANT
)
5388 memcpy(&args
[argspos
], arg
, _argsize(prgvt
[i
]) * sizeof(DWORD
));
5390 memcpy(&args
[argspos
], &V_NONE(arg
), _argsize(prgvt
[i
]) * sizeof(DWORD
));
5391 argspos
+= _argsize(prgvt
[i
]);
5396 FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
5397 hres
= _invoke(vtable
[oVft
/sizeof(void *)], cc
, argsize
, args
);
5400 /* if we aren't invoking an object then the function pointer is stored
5402 hres
= _invoke((FARPROC
)oVft
, cc
, argsize
, args
);
5404 if (pvargResult
&& (vtReturn
!= VT_EMPTY
))
5406 TRACE("Method returned 0x%08x\n",hres
);
5407 V_VT(pvargResult
) = vtReturn
;
5408 V_UI4(pvargResult
) = hres
;
5411 HeapFree(GetProcessHeap(),0,args
);
5415 #define INVBUF_ELEMENT_SIZE \
5416 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5417 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5418 ((VARIANTARG *)(buffer))
5419 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5420 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5421 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5422 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5423 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5424 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5426 static HRESULT WINAPI
ITypeInfo_fnInvoke(
5431 DISPPARAMS
*pDispParams
,
5432 VARIANT
*pVarResult
,
5433 EXCEPINFO
*pExcepInfo
,
5436 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5438 unsigned int var_index
;
5441 const TLBFuncDesc
*pFuncInfo
;
5443 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5444 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
5449 ERR("NULL pDispParams not allowed\n");
5450 return E_INVALIDARG
;
5453 dump_DispParms(pDispParams
);
5455 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
5457 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5458 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
5459 return E_INVALIDARG
;
5462 /* we do this instead of using GetFuncDesc since it will return a fake
5463 * FUNCDESC for dispinterfaces and we want the real function description */
5464 for (pFuncInfo
= This
->funclist
; pFuncInfo
; pFuncInfo
=pFuncInfo
->next
)
5465 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
5466 (wFlags
& pFuncInfo
->funcdesc
.invkind
))
5470 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
5474 TRACE("invoking:\n");
5475 dump_TLBFuncDescOne(pFuncInfo
);
5478 switch (func_desc
->funckind
) {
5479 case FUNC_PUREVIRTUAL
:
5480 case FUNC_VIRTUAL
: {
5481 void *buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
5483 VARIANT retval
; /* pointer for storing byref retvals in */
5484 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
5485 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
5486 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
5487 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
5488 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
5492 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
5494 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
5496 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5497 hres
= DISP_E_PARAMNOTFOUND
;
5500 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5502 rgdispidNamedArgs
++;
5505 for (i
= 0; i
< func_desc
->cParams
; i
++)
5507 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
5508 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
5513 TRACE("changing args\n");
5514 for (i
= 0; i
< func_desc
->cParams
; i
++)
5516 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
5517 VARIANTARG
*src_arg
;
5523 for (j
= 0; j
< cNamedArgs
; j
++)
5524 if (rgdispidNamedArgs
[j
] == i
)
5526 src_arg
= &pDispParams
->rgvarg
[j
];
5531 src_arg
= i
< pDispParams
->cArgs
? &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
] : NULL
;
5533 if (wParamFlags
& PARAMFLAG_FRETVAL
)
5535 /* under most conditions the caller is not allowed to
5536 * pass in a dispparam arg in the index of what would be
5537 * the retval parameter. however, there is an exception
5538 * where the extra parameter is used in an extra
5539 * IDispatch::Invoke below */
5540 if ((i
< pDispParams
->cArgs
) &&
5541 ((func_desc
->cParams
!= 1) || !pVarResult
||
5542 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
5544 hres
= DISP_E_BADPARAMCOUNT
;
5548 /* note: this check is placed so that if the caller passes
5549 * in a VARIANTARG for the retval we just ignore it, like
5551 if (i
== func_desc
->cParams
- 1)
5554 arg
= prgpvarg
[i
] = &rgvarg
[i
];
5555 memset(arg
, 0, sizeof(*arg
));
5556 V_VT(arg
) = rgvt
[i
];
5557 memset(&retval
, 0, sizeof(retval
));
5558 V_BYREF(arg
) = &retval
;
5562 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
5563 hres
= E_UNEXPECTED
;
5569 dump_Variant(src_arg
);
5571 if (rgvt
[i
] == VT_VARIANT
)
5572 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
5573 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
5575 if (rgvt
[i
] == V_VT(src_arg
))
5576 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
5579 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
5580 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
5581 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
5583 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5585 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
5587 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
5588 V_VT(&missing_arg
[i
]) = V_VT(src_arg
);
5589 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
5590 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
5591 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5593 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
5595 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
5596 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5600 /* FIXME: this doesn't work for VT_BYREF arguments if
5601 * they are not the same type as in the paramdesc */
5602 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
5603 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
5604 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5609 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
5610 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
5611 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
5614 prgpvarg
[i
] = &rgvarg
[i
];
5616 else if (wParamFlags
& PARAMFLAG_FOPT
)
5619 arg
= prgpvarg
[i
] = &rgvarg
[i
];
5620 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5622 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
5628 VARIANTARG
*missing_arg
;
5629 /* if the function wants a pointer to a variant then
5630 * set that up, otherwise just pass the VT_ERROR in
5631 * the argument by value */
5632 if (rgvt
[i
] & VT_BYREF
)
5634 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
5635 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
5636 V_VARIANTREF(arg
) = missing_arg
;
5640 V_VT(missing_arg
) = VT_ERROR
;
5641 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
5646 hres
= DISP_E_BADPARAMCOUNT
;
5650 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
5651 if (func_desc
->cParamsOpt
< 0)
5653 FIXME("Does not support safearray optional parameters\n");
5654 hres
= DISP_E_BADPARAMCOUNT
;
5655 goto func_fail
; /* FIXME: we don't free changed types here */
5658 /* VT_VOID is a special case for return types, so it is not
5659 * handled in the general function */
5660 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
5661 V_VT(&varresult
) = VT_EMPTY
;
5664 V_VT(&varresult
) = 0;
5665 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
5666 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
5669 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
, func_desc
->callconv
,
5670 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
5671 prgpvarg
, &varresult
);
5673 for (i
= 0; i
< func_desc
->cParams
; i
++)
5675 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
5676 if (wParamFlags
& PARAMFLAG_FRETVAL
)
5680 TRACE("[retval] value: ");
5681 dump_Variant(prgpvarg
[i
]);
5686 VariantInit(pVarResult
);
5687 /* deref return value */
5688 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
5691 /* free data stored in varresult. Note that
5692 * VariantClear doesn't do what we want because we are
5693 * working with byref types. */
5694 /* FIXME: clear safearrays, bstrs, records and
5695 * variants here too */
5696 if ((V_VT(prgpvarg
[i
]) == (VT_UNKNOWN
| VT_BYREF
)) ||
5697 (V_VT(prgpvarg
[i
]) == (VT_DISPATCH
| VT_BYREF
)))
5699 if(*V_UNKNOWNREF(prgpvarg
[i
]))
5700 IUnknown_Release(*V_UNKNOWNREF(prgpvarg
[i
]));
5704 else if (i
< pDispParams
->cArgs
)
5706 if (wParamFlags
& PARAMFLAG_FOUT
)
5708 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
];
5710 if ((rgvt
[i
] == VT_BYREF
) && (V_VT(arg
) != VT_BYREF
))
5711 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
5715 ERR("failed to convert param %d to vt %d\n", i
,
5716 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
]));
5720 VariantClear(&rgvarg
[i
]);
5722 else if (wParamFlags
& PARAMFLAG_FOPT
)
5724 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5725 VariantClear(&rgvarg
[i
]);
5729 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
5731 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
5732 hres
= DISP_E_EXCEPTION
;
5735 IErrorInfo
*pErrorInfo
;
5736 pExcepInfo
->scode
= V_ERROR(&varresult
);
5737 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
5739 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
5740 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
5741 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
5742 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
5744 IErrorInfo_Release(pErrorInfo
);
5748 if (V_VT(&varresult
) != VT_ERROR
)
5750 TRACE("varresult value: ");
5751 dump_Variant(&varresult
);
5755 VariantClear(pVarResult
);
5756 *pVarResult
= varresult
;
5759 VariantClear(&varresult
);
5762 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
5763 (wFlags
== INVOKE_PROPERTYGET
) &&
5764 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
5765 (pDispParams
->cArgs
!= 0))
5767 if (V_VT(pVarResult
) == VT_DISPATCH
)
5769 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
5770 /* Note: not VariantClear; we still need the dispatch
5771 * pointer to be valid */
5772 VariantInit(pVarResult
);
5773 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
5774 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
5775 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
5776 IDispatch_Release(pDispatch
);
5780 VariantClear(pVarResult
);
5781 hres
= DISP_E_NOTACOLLECTION
;
5786 HeapFree(GetProcessHeap(), 0, buffer
);
5789 case FUNC_DISPATCH
: {
5792 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
5793 if (SUCCEEDED(hres
)) {
5794 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5795 hres
= IDispatch_Invoke(
5796 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
5797 pVarResult
,pExcepInfo
,pArgErr
5800 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
5801 IDispatch_Release(disp
);
5803 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5807 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
5812 TRACE("-- 0x%08x\n", hres
);
5815 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
5818 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
5819 if(FAILED(hres
)) return hres
;
5821 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5822 dump_VARDESC(var_desc
);
5823 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
5827 /* not found, look for it in inherited interfaces */
5828 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
5829 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
5830 if(This
->impltypelist
) {
5831 /* recursive search */
5833 hres
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pTInfo
);
5834 if(SUCCEEDED(hres
)){
5835 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
5836 ITypeInfo_Release(pTInfo
);
5839 WARN("Could not search inherited interface!\n");
5842 ERR("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
5843 return DISP_E_MEMBERNOTFOUND
;
5846 /* ITypeInfo::GetDocumentation
5848 * Retrieves the documentation string, the complete Help file name and path,
5849 * and the context ID for the Help topic for a specified type description.
5851 * (Can be tested by the Visual Basic Editor in Word for instance.)
5853 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
5854 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
5855 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
5857 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5858 const TLBFuncDesc
*pFDesc
;
5859 const TLBVarDesc
*pVDesc
;
5860 TRACE("(%p) memid %d Name(%p) DocString(%p)"
5861 " HelpContext(%p) HelpFile(%p)\n",
5862 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
5863 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5865 *pBstrName
=SysAllocString(This
->Name
);
5867 *pBstrDocString
=SysAllocString(This
->DocString
);
5869 *pdwHelpContext
=This
->dwHelpContext
;
5871 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
5873 }else {/* for a member */
5874 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5875 if(pFDesc
->funcdesc
.memid
==memid
){
5877 *pBstrName
= SysAllocString(pFDesc
->Name
);
5879 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
5881 *pdwHelpContext
=pFDesc
->helpcontext
;
5884 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5885 if(pVDesc
->vardesc
.memid
==memid
){
5887 *pBstrName
= SysAllocString(pVDesc
->Name
);
5889 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
5891 *pdwHelpContext
=pVDesc
->HelpContext
;
5896 if(This
->impltypelist
&&
5897 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
5898 /* recursive search */
5901 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
5903 if(SUCCEEDED(result
)) {
5904 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
5905 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
5906 ITypeInfo_Release(pTInfo
);
5909 WARN("Could not search inherited interface!\n");
5912 WARN("member %d not found\n", memid
);
5913 return TYPE_E_ELEMENTNOTFOUND
;
5916 /* ITypeInfo::GetDllEntry
5918 * Retrieves a description or specification of an entry point for a function
5921 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
5922 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
5925 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5926 const TLBFuncDesc
*pFDesc
;
5928 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
5930 if (pBstrDllName
) *pBstrDllName
= NULL
;
5931 if (pBstrName
) *pBstrName
= NULL
;
5932 if (pwOrdinal
) *pwOrdinal
= 0;
5934 if (This
->TypeAttr
.typekind
!= TKIND_MODULE
)
5935 return TYPE_E_BADMODULEKIND
;
5937 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5938 if(pFDesc
->funcdesc
.memid
==memid
){
5939 dump_TypeInfo(This
);
5941 dump_TLBFuncDescOne(pFDesc
);
5944 *pBstrDllName
= SysAllocString(This
->DllName
);
5946 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
5948 *pBstrName
= SysAllocString(pFDesc
->Entry
);
5956 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
5959 return TYPE_E_ELEMENTNOTFOUND
;
5962 /* ITypeInfo::GetRefTypeInfo
5964 * If a type description references other type descriptions, it retrieves
5965 * the referenced type descriptions.
5967 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
5970 ITypeInfo
**ppTInfo
)
5972 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5973 HRESULT result
= E_FAIL
;
5975 if ((This
->hreftype
!= -1) && (This
->hreftype
== hRefType
))
5977 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5978 ITypeInfo_AddRef(*ppTInfo
);
5981 else if (hRefType
== -1 &&
5982 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
5983 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
5985 /* when we meet a DUAL dispinterface, we must create the interface
5988 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
5991 /* the interface version contains the same information as the dispinterface
5992 * copy the contents of the structs.
5994 *pTypeInfoImpl
= *This
;
5995 pTypeInfoImpl
->ref
= 0;
5997 /* change the type to interface */
5998 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
6000 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
6002 /* we use data structures from This, so we need to keep a reference
6003 * to it to stop it being destroyed and signal to the new instance to
6004 * not free its data structures when it is destroyed */
6005 pTypeInfoImpl
->no_free_data
= TRUE
;
6006 pTypeInfoImpl
->next
= This
;
6007 ITypeInfo_AddRef((ITypeInfo
*) This
);
6009 ITypeInfo_AddRef(*ppTInfo
);
6014 TLBRefType
*ref_type
;
6015 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
6017 if(ref_type
->reference
== hRefType
)
6020 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
6022 FIXME("Can't find pRefType for ref %x\n", hRefType
);
6025 if(hRefType
!= -1) {
6026 ITypeLib
*pTLib
= NULL
;
6028 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
6030 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
6032 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
6033 TRACE("typeinfo in imported typelib that is already loaded\n");
6034 pTLib
= (ITypeLib
*)ref_type
->pImpTLInfo
->pImpTypeLib
;
6035 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
6038 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6039 result
= LoadRegTypeLib( &ref_type
->pImpTLInfo
->guid
,
6040 ref_type
->pImpTLInfo
->wVersionMajor
,
6041 ref_type
->pImpTLInfo
->wVersionMinor
,
6042 ref_type
->pImpTLInfo
->lcid
,
6045 if(!SUCCEEDED(result
)) {
6046 BSTR libnam
=SysAllocString(ref_type
->pImpTLInfo
->name
);
6047 result
=LoadTypeLib(libnam
, &pTLib
);
6048 SysFreeString(libnam
);
6050 if(SUCCEEDED(result
)) {
6051 ref_type
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
6052 ITypeLib2_AddRef(pTLib
);
6056 if(SUCCEEDED(result
)) {
6057 if(ref_type
->index
== TLB_REF_USE_GUID
)
6058 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
6062 result
= ITypeLib2_GetTypeInfo(pTLib
, ref_type
->index
,
6066 ITypeLib2_Release(pTLib
);
6071 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
6072 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
6076 /* ITypeInfo::AddressOfMember
6078 * Retrieves the addresses of static functions or variables, such as those
6081 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
6082 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
6084 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6090 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
6092 hr
= ITypeInfo_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
6096 module
= LoadLibraryW(dll
);
6099 ERR("couldn't load %s\n", debugstr_w(dll
));
6101 if (entry
) SysFreeString(entry
);
6102 return STG_E_FILENOTFOUND
;
6104 /* FIXME: store library somewhere where we can free it */
6109 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
6110 entryA
= HeapAlloc(GetProcessHeap(), 0, len
);
6111 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
6113 *ppv
= GetProcAddress(module
, entryA
);
6115 ERR("function not found %s\n", debugstr_a(entryA
));
6117 HeapFree(GetProcessHeap(), 0, entryA
);
6121 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
6123 ERR("function not found %d\n", ordinal
);
6127 if (entry
) SysFreeString(entry
);
6130 return TYPE_E_DLLFUNCTIONNOTFOUND
;
6135 /* ITypeInfo::CreateInstance
6137 * Creates a new instance of a type that describes a component object class
6140 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
6141 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
6143 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6147 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
6153 WARN("Not able to aggregate\n");
6154 return CLASS_E_NOAGGREGATION
;
6157 hr
= ITypeInfo_GetTypeAttr(iface
, &pTA
);
6158 if(FAILED(hr
)) return hr
;
6160 if(pTA
->typekind
!= TKIND_COCLASS
)
6162 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
6168 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
6171 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
6172 TRACE("GetActiveObject rets %08x\n", hr
);
6175 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
6176 IUnknown_Release(pUnk
);
6181 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
6182 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
6186 ITypeInfo_ReleaseTypeAttr(iface
, pTA
);
6190 /* ITypeInfo::GetMops
6192 * Retrieves marshalling information.
6194 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
6197 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6198 FIXME("(%p) stub!\n", This
);
6202 /* ITypeInfo::GetContainingTypeLib
6204 * Retrieves the containing type library and the index of the type description
6205 * within that type library.
6207 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
6208 ITypeLib
* *ppTLib
, UINT
*pIndex
)
6210 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6212 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6214 *pIndex
=This
->index
;
6215 TRACE("returning pIndex=%d\n", *pIndex
);
6219 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
6220 ITypeLib2_AddRef(*ppTLib
);
6221 TRACE("returning ppTLib=%p\n", *ppTLib
);
6227 /* ITypeInfo::ReleaseTypeAttr
6229 * Releases a TYPEATTR previously returned by GetTypeAttr.
6232 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
6233 TYPEATTR
* pTypeAttr
)
6235 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6236 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
6237 HeapFree(GetProcessHeap(), 0, pTypeAttr
);
6240 /* ITypeInfo::ReleaseFuncDesc
6242 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6244 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
6246 FUNCDESC
*pFuncDesc
)
6248 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6251 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
6253 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6254 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
6255 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
6257 SysFreeString((BSTR
)pFuncDesc
);
6260 /* ITypeInfo::ReleaseVarDesc
6262 * Releases a VARDESC previously returned by GetVarDesc.
6264 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
6267 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6268 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
6270 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
6271 if (pVarDesc
->varkind
== VAR_CONST
)
6272 VariantClear(pVarDesc
->u
.lpvarValue
);
6273 SysFreeString((BSTR
)pVarDesc
);
6276 /* ITypeInfo2::GetTypeKind
6278 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6281 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
6282 TYPEKIND
*pTypeKind
)
6284 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6285 *pTypeKind
=This
->TypeAttr
.typekind
;
6286 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
6290 /* ITypeInfo2::GetTypeFlags
6292 * Returns the type flags without any allocations. This returns a DWORD type
6293 * flag, which expands the type flags without growing the TYPEATTR (type
6297 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
6299 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6300 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
6301 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
6305 /* ITypeInfo2::GetFuncIndexOfMemId
6306 * Binds to a specific member based on a known DISPID, where the member name
6307 * is not known (for example, when binding to a default member).
6310 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
6311 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
6313 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6314 const TLBFuncDesc
*pFuncInfo
;
6318 for(i
= 0, pFuncInfo
= This
->funclist
; pFuncInfo
; i
++, pFuncInfo
=pFuncInfo
->next
)
6319 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
6325 result
= TYPE_E_ELEMENTNOTFOUND
;
6327 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
6328 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
6332 /* TypeInfo2::GetVarIndexOfMemId
6334 * Binds to a specific member based on a known DISPID, where the member name
6335 * is not known (for example, when binding to a default member).
6338 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
6339 MEMBERID memid
, UINT
*pVarIndex
)
6341 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6342 TLBVarDesc
*pVarInfo
;
6345 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
6346 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
6352 result
= TYPE_E_ELEMENTNOTFOUND
;
6354 TRACE("(%p) memid 0x%08x -> %s\n", This
,
6355 memid
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
6359 /* ITypeInfo2::GetCustData
6361 * Gets the custom data
6363 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
6368 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6369 TLBCustData
*pCData
;
6371 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
6372 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6374 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6378 VariantInit( pVarVal
);
6379 VariantCopy( pVarVal
, &pCData
->data
);
6382 return E_INVALIDARG
; /* FIXME: correct? */
6385 /* ITypeInfo2::GetFuncCustData
6387 * Gets the custom data
6389 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
6395 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6396 TLBCustData
*pCData
=NULL
;
6397 TLBFuncDesc
* pFDesc
;
6399 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
6400 pFDesc
=pFDesc
->next
);
6403 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
6404 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6406 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6409 VariantInit( pVarVal
);
6410 VariantCopy( pVarVal
, &pCData
->data
);
6413 return E_INVALIDARG
; /* FIXME: correct? */
6416 /* ITypeInfo2::GetParamCustData
6418 * Gets the custom data
6420 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
6427 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6428 TLBCustData
*pCData
=NULL
;
6429 TLBFuncDesc
* pFDesc
;
6432 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
6434 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
6435 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
6436 pCData
= pCData
->next
)
6437 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6439 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6443 VariantInit( pVarVal
);
6444 VariantCopy( pVarVal
, &pCData
->data
);
6447 return E_INVALIDARG
; /* FIXME: correct? */
6450 /* ITypeInfo2::GetVarCustData
6452 * Gets the custom data
6454 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
6460 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6461 TLBCustData
*pCData
=NULL
;
6462 TLBVarDesc
* pVDesc
;
6465 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
6469 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
6471 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6475 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6479 VariantInit( pVarVal
);
6480 VariantCopy( pVarVal
, &pCData
->data
);
6483 return E_INVALIDARG
; /* FIXME: correct? */
6486 /* ITypeInfo2::GetImplCustData
6488 * Gets the custom data
6490 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
6496 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6497 TLBCustData
*pCData
=NULL
;
6498 TLBImplType
* pRDesc
;
6501 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
6505 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
6507 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6511 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6515 VariantInit( pVarVal
);
6516 VariantCopy( pVarVal
, &pCData
->data
);
6519 return E_INVALIDARG
; /* FIXME: correct? */
6522 /* ITypeInfo2::GetDocumentation2
6524 * Retrieves the documentation string, the complete Help file name and path,
6525 * the localization context to use, and the context ID for the library Help
6526 * topic in the Help file.
6529 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
6533 BSTR
*pbstrHelpString
,
6534 DWORD
*pdwHelpStringContext
,
6535 BSTR
*pbstrHelpStringDll
)
6537 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6538 const TLBFuncDesc
*pFDesc
;
6539 const TLBVarDesc
*pVDesc
;
6540 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6541 "HelpStringContext(%p) HelpStringDll(%p)\n",
6542 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
6543 pbstrHelpStringDll
);
6544 /* the help string should be obtained from the helpstringdll,
6545 * using the _DLLGetDocumentation function, based on the supplied
6546 * lcid. Nice to do sometime...
6548 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
6550 *pbstrHelpString
=SysAllocString(This
->Name
);
6551 if(pdwHelpStringContext
)
6552 *pdwHelpStringContext
=This
->dwHelpStringContext
;
6553 if(pbstrHelpStringDll
)
6554 *pbstrHelpStringDll
=
6555 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6557 }else {/* for a member */
6558 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6559 if(pFDesc
->funcdesc
.memid
==memid
){
6561 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
6562 if(pdwHelpStringContext
)
6563 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
6564 if(pbstrHelpStringDll
)
6565 *pbstrHelpStringDll
=
6566 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6569 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
6570 if(pVDesc
->vardesc
.memid
==memid
){
6572 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
6573 if(pdwHelpStringContext
)
6574 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
6575 if(pbstrHelpStringDll
)
6576 *pbstrHelpStringDll
=
6577 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6581 return TYPE_E_ELEMENTNOTFOUND
;
6584 /* ITypeInfo2::GetAllCustData
6586 * Gets all custom data items for the Type info.
6589 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
6591 CUSTDATA
*pCustData
)
6593 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6594 TLBCustData
*pCData
;
6597 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
6599 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
6600 if(pCustData
->prgCustData
){
6601 pCustData
->cCustData
=This
->ctCustData
;
6602 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
6603 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6604 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
6607 ERR(" OUT OF MEMORY!\n");
6608 return E_OUTOFMEMORY
;
6613 /* ITypeInfo2::GetAllFuncCustData
6615 * Gets all custom data items for the specified Function
6618 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
6621 CUSTDATA
*pCustData
)
6623 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6624 TLBCustData
*pCData
;
6625 TLBFuncDesc
* pFDesc
;
6627 TRACE("(%p) index %d\n", This
, index
);
6628 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
6629 pFDesc
=pFDesc
->next
)
6632 pCustData
->prgCustData
=
6633 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
6634 if(pCustData
->prgCustData
){
6635 pCustData
->cCustData
=pFDesc
->ctCustData
;
6636 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
6637 pCData
= pCData
->next
){
6638 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6639 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6643 ERR(" OUT OF MEMORY!\n");
6644 return E_OUTOFMEMORY
;
6648 return TYPE_E_ELEMENTNOTFOUND
;
6651 /* ITypeInfo2::GetAllParamCustData
6653 * Gets all custom data items for the Functions
6656 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
6657 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
6659 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6660 TLBCustData
*pCData
=NULL
;
6661 TLBFuncDesc
* pFDesc
;
6663 TRACE("(%p) index %d\n", This
, indexFunc
);
6664 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
6665 pFDesc
=pFDesc
->next
)
6667 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
6668 pCustData
->prgCustData
=
6669 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
6670 sizeof(CUSTDATAITEM
));
6671 if(pCustData
->prgCustData
){
6672 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
6673 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
6674 pCData
; i
++, pCData
= pCData
->next
){
6675 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6676 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6680 ERR(" OUT OF MEMORY!\n");
6681 return E_OUTOFMEMORY
;
6685 return TYPE_E_ELEMENTNOTFOUND
;
6688 /* ITypeInfo2::GetAllVarCustData
6690 * Gets all custom data items for the specified Variable
6693 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
6694 UINT index
, CUSTDATA
*pCustData
)
6696 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6697 TLBCustData
*pCData
;
6698 TLBVarDesc
* pVDesc
;
6700 TRACE("(%p) index %d\n", This
, index
);
6701 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
6702 pVDesc
=pVDesc
->next
)
6705 pCustData
->prgCustData
=
6706 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
6707 if(pCustData
->prgCustData
){
6708 pCustData
->cCustData
=pVDesc
->ctCustData
;
6709 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
6710 pCData
= pCData
->next
){
6711 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6712 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6716 ERR(" OUT OF MEMORY!\n");
6717 return E_OUTOFMEMORY
;
6721 return TYPE_E_ELEMENTNOTFOUND
;
6724 /* ITypeInfo2::GetAllImplCustData
6726 * Gets all custom data items for the specified implementation type
6729 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
6732 CUSTDATA
*pCustData
)
6734 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6735 TLBCustData
*pCData
;
6736 TLBImplType
* pRDesc
;
6738 TRACE("(%p) index %d\n", This
, index
);
6739 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
6740 pRDesc
=pRDesc
->next
)
6743 pCustData
->prgCustData
=
6744 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
6745 if(pCustData
->prgCustData
){
6746 pCustData
->cCustData
=pRDesc
->ctCustData
;
6747 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
6748 pCData
= pCData
->next
){
6749 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6750 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6754 ERR(" OUT OF MEMORY!\n");
6755 return E_OUTOFMEMORY
;
6759 return TYPE_E_ELEMENTNOTFOUND
;
6762 static const ITypeInfo2Vtbl tinfvt
=
6765 ITypeInfo_fnQueryInterface
,
6767 ITypeInfo_fnRelease
,
6769 ITypeInfo_fnGetTypeAttr
,
6770 ITypeInfo_fnGetTypeComp
,
6771 ITypeInfo_fnGetFuncDesc
,
6772 ITypeInfo_fnGetVarDesc
,
6773 ITypeInfo_fnGetNames
,
6774 ITypeInfo_fnGetRefTypeOfImplType
,
6775 ITypeInfo_fnGetImplTypeFlags
,
6776 ITypeInfo_fnGetIDsOfNames
,
6778 ITypeInfo_fnGetDocumentation
,
6779 ITypeInfo_fnGetDllEntry
,
6780 ITypeInfo_fnGetRefTypeInfo
,
6781 ITypeInfo_fnAddressOfMember
,
6782 ITypeInfo_fnCreateInstance
,
6783 ITypeInfo_fnGetMops
,
6784 ITypeInfo_fnGetContainingTypeLib
,
6785 ITypeInfo_fnReleaseTypeAttr
,
6786 ITypeInfo_fnReleaseFuncDesc
,
6787 ITypeInfo_fnReleaseVarDesc
,
6789 ITypeInfo2_fnGetTypeKind
,
6790 ITypeInfo2_fnGetTypeFlags
,
6791 ITypeInfo2_fnGetFuncIndexOfMemId
,
6792 ITypeInfo2_fnGetVarIndexOfMemId
,
6793 ITypeInfo2_fnGetCustData
,
6794 ITypeInfo2_fnGetFuncCustData
,
6795 ITypeInfo2_fnGetParamCustData
,
6796 ITypeInfo2_fnGetVarCustData
,
6797 ITypeInfo2_fnGetImplTypeCustData
,
6798 ITypeInfo2_fnGetDocumentation2
,
6799 ITypeInfo2_fnGetAllCustData
,
6800 ITypeInfo2_fnGetAllFuncCustData
,
6801 ITypeInfo2_fnGetAllParamCustData
,
6802 ITypeInfo2_fnGetAllVarCustData
,
6803 ITypeInfo2_fnGetAllImplTypeCustData
,
6806 /******************************************************************************
6807 * CreateDispTypeInfo [OLEAUT32.31]
6809 * Build type information for an object so it can be called through an
6810 * IDispatch interface.
6813 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6814 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6817 * This call allows an objects methods to be accessed through IDispatch, by
6818 * building an ITypeInfo object that IDispatch can use to call through.
6820 HRESULT WINAPI
CreateDispTypeInfo(
6821 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
6822 LCID lcid
, /* [I] Locale Id */
6823 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
6825 ITypeInfoImpl
*pTIClass
, *pTIIface
;
6826 ITypeLibImpl
*pTypeLibImpl
;
6828 TLBFuncDesc
**ppFuncDesc
;
6832 pTypeLibImpl
= TypeLibImpl_Constructor();
6833 if (!pTypeLibImpl
) return E_FAIL
;
6835 pTIIface
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
6836 pTIIface
->pTypeLib
= pTypeLibImpl
;
6837 pTIIface
->index
= 0;
6838 pTIIface
->Name
= NULL
;
6839 pTIIface
->dwHelpContext
= -1;
6840 memset(&pTIIface
->TypeAttr
.guid
, 0, sizeof(GUID
));
6841 pTIIface
->TypeAttr
.lcid
= lcid
;
6842 pTIIface
->TypeAttr
.typekind
= TKIND_INTERFACE
;
6843 pTIIface
->TypeAttr
.wMajorVerNum
= 0;
6844 pTIIface
->TypeAttr
.wMinorVerNum
= 0;
6845 pTIIface
->TypeAttr
.cbAlignment
= 2;
6846 pTIIface
->TypeAttr
.cbSizeInstance
= -1;
6847 pTIIface
->TypeAttr
.cbSizeVft
= -1;
6848 pTIIface
->TypeAttr
.cFuncs
= 0;
6849 pTIIface
->TypeAttr
.cImplTypes
= 0;
6850 pTIIface
->TypeAttr
.cVars
= 0;
6851 pTIIface
->TypeAttr
.wTypeFlags
= 0;
6853 ppFuncDesc
= &pTIIface
->funclist
;
6854 for(func
= 0; func
< pidata
->cMembers
; func
++) {
6855 METHODDATA
*md
= pidata
->pmethdata
+ func
;
6856 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
6857 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
6858 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
6859 (*ppFuncDesc
)->funcdesc
.lprgscode
= NULL
;
6860 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_VIRTUAL
;
6861 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
6862 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
6863 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
6864 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
6865 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
<< 2;
6866 (*ppFuncDesc
)->funcdesc
.cScodes
= 0;
6867 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0;
6868 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
6869 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
6870 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
6871 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
6872 md
->cArgs
* sizeof(ELEMDESC
));
6873 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
6874 md
->cArgs
* sizeof(TLBParDesc
));
6875 for(param
= 0; param
< md
->cArgs
; param
++) {
6876 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
6877 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
6879 (*ppFuncDesc
)->helpcontext
= 0;
6880 (*ppFuncDesc
)->HelpStringContext
= 0;
6881 (*ppFuncDesc
)->HelpString
= NULL
;
6882 (*ppFuncDesc
)->Entry
= NULL
;
6883 (*ppFuncDesc
)->ctCustData
= 0;
6884 (*ppFuncDesc
)->pCustData
= NULL
;
6885 (*ppFuncDesc
)->next
= NULL
;
6886 pTIIface
->TypeAttr
.cFuncs
++;
6887 ppFuncDesc
= &(*ppFuncDesc
)->next
;
6890 dump_TypeInfo(pTIIface
);
6892 pTypeLibImpl
->pTypeInfo
= pTIIface
;
6893 pTypeLibImpl
->TypeInfoCount
++;
6895 pTIClass
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
6896 pTIClass
->pTypeLib
= pTypeLibImpl
;
6897 pTIClass
->index
= 1;
6898 pTIClass
->Name
= NULL
;
6899 pTIClass
->dwHelpContext
= -1;
6900 memset(&pTIClass
->TypeAttr
.guid
, 0, sizeof(GUID
));
6901 pTIClass
->TypeAttr
.lcid
= lcid
;
6902 pTIClass
->TypeAttr
.typekind
= TKIND_COCLASS
;
6903 pTIClass
->TypeAttr
.wMajorVerNum
= 0;
6904 pTIClass
->TypeAttr
.wMinorVerNum
= 0;
6905 pTIClass
->TypeAttr
.cbAlignment
= 2;
6906 pTIClass
->TypeAttr
.cbSizeInstance
= -1;
6907 pTIClass
->TypeAttr
.cbSizeVft
= -1;
6908 pTIClass
->TypeAttr
.cFuncs
= 0;
6909 pTIClass
->TypeAttr
.cImplTypes
= 1;
6910 pTIClass
->TypeAttr
.cVars
= 0;
6911 pTIClass
->TypeAttr
.wTypeFlags
= 0;
6913 pTIClass
->impltypelist
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pTIClass
->impltypelist
));
6914 pTIClass
->impltypelist
->hRef
= 0;
6916 ref
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ref
));
6919 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
6920 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
6922 dump_TypeInfo(pTIClass
);
6924 pTIIface
->next
= pTIClass
;
6925 pTypeLibImpl
->TypeInfoCount
++;
6927 *pptinfo
= (ITypeInfo
*)pTIClass
;
6929 ITypeInfo_AddRef(*pptinfo
);
6930 ITypeLib_Release((ITypeLib
*)&pTypeLibImpl
->lpVtbl
);
6936 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
6938 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6940 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
6943 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
6945 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6947 return ITypeInfo_AddRef((ITypeInfo
*)This
);
6950 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
6952 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6954 return ITypeInfo_Release((ITypeInfo
*)This
);
6957 static HRESULT WINAPI
ITypeComp_fnBind(
6962 ITypeInfo
** ppTInfo
,
6963 DESCKIND
* pDescKind
,
6966 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6967 const TLBFuncDesc
*pFDesc
;
6968 const TLBVarDesc
*pVDesc
;
6969 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
6971 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
6973 *pDescKind
= DESCKIND_NONE
;
6974 pBindPtr
->lpfuncdesc
= NULL
;
6977 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
6978 if (!strcmpiW(pFDesc
->Name
, szName
)) {
6979 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
6982 /* name found, but wrong flags */
6983 hr
= TYPE_E_TYPEMISMATCH
;
6988 HRESULT hr
= TLB_AllocAndInitFuncDesc(
6990 &pBindPtr
->lpfuncdesc
,
6991 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
6994 *pDescKind
= DESCKIND_FUNCDESC
;
6995 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6996 ITypeInfo_AddRef(*ppTInfo
);
6999 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
7000 if (!strcmpiW(pVDesc
->Name
, szName
)) {
7001 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
7004 *pDescKind
= DESCKIND_VARDESC
;
7005 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7006 ITypeInfo_AddRef(*ppTInfo
);
7011 /* FIXME: search each inherited interface, not just the first */
7012 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypelist
) {
7013 /* recursive search */
7017 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
7020 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
7021 ITypeInfo_Release(pTInfo
);
7025 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7026 ITypeComp_Release(pTComp
);
7029 WARN("Could not search inherited interface!\n");
7031 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
7035 static HRESULT WINAPI
ITypeComp_fnBindType(
7039 ITypeInfo
** ppTInfo
,
7040 ITypeComp
** ppTComp
)
7042 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
7044 /* strange behaviour (does nothing) but like the
7047 if (!ppTInfo
|| !ppTComp
)
7056 static const ITypeCompVtbl tcompvt
=
7059 ITypeComp_fnQueryInterface
,
7061 ITypeComp_fnRelease
,
7064 ITypeComp_fnBindType